views:

412

answers:

2

I am trying to test a proof of concept that I can run a distributed transaction across two linked SQL Servers, linked using sp_addlinkedserver - their names are Server1 and Server2, both running under default instances. Each server holds a single database, Source and Destination respectively and the destination database holds a single table called Output, i.e.

Server1.Source
Server2.Destination.Output

The OUTPUT table has the following structure:

OUT_PKEY int identity(1,1) primary key,
OUT_TEXT nvarchar(255)

From Server1 I have called *sp_addlinkedserver 'Server2'* to link the two databases and I've attempted to run the following query to test that the link does indeed work:

Select   *
From     Server2.Destination.dbo.Output

I am returned the following exception:

Access to the remote server is denied because no login-mapping exists.

Fair enough, so from Server1, I run *sp_addlinkedsrvlogin 'Server2'* which according to the documentation says that it should take the user credentials of whomever runs the query remotely (i.e. from Server1) and apply those credentials to Server2. This implies that since I am connected to Server1 using Windows Authentication, this should mean that my Windows Credentials are applied to Server2 also.

Now the exception message changes to:

Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.

Having Googled this exception, I came up with nothing useful that pointed me in the right direction. What am I missing? I would expect [should the login fail at all] the exception to reference my Windows Credentials, not the anonymous logon credentials.

It looks like once I get the link itself working, the distributed transactions themselves should be a fairly simple affair - the documentation implies that I just need to ensure that the DTC Service is running on Server1 and that any queries run on Server1 that will be transacted across the link:

  • Include *SET XACT_ABORT ON* prior to initializing my distributed transaction
  • I use BEGIN DISTRIBUTED TRANSACTION instead of BEGIN TRANSACTION
  • If I wish to reference a non-default instance of SQL Server on Server2, I replace any instances of the name Server2 in my query with [Server2\InstanceName]

My questions are these:

  • how do I get past this login issue? The *sp_addlinkedsrvlogin* stored procedure alone doesn't seem to be doing the trick.
  • Is it indeed as simple as that to run the distributed transaction as the documentation implies?

TIA

A: 

Assuming these servers are both on the same domain - have you enabled trusted delegation to allow your server to pass the credentials to the targeted server? You would pull up the Active Directory object for the server and go to the Delegation tab and select "Trust this computer for delegation to specified services only" and then enter the SQL Server details that the server is allowed to pass credentials to:

Service Type = MSSQLSvc
User/Computer = YourTargetServer.Your.Domain
Port = 1433

Sadly, a lot of these types of authentication issues with linked servers require a reboot to fully take effect (so if these are production servers it is hard to troubleshoot during the day).

In regards to distributed transactions - if you eventually get the linked server connection up and running correctly then distributed transactions work great. Although the next thing you'll probably run into once you get it working is finding the huge flaw that you can't use any form of SCOPE_IDENTITY(), @@IDENTITY, etc. to retrieve primary keys after inserting something into a linked database. But that's another issue with its own fun workarounds...

Lance McNearney
+1  A: 

If you're on a domain, then the setting should be "Be made using the login's current security context", but there's one more step - you need to grant an SPN to each of the servers involved in the transaction.

Assuming you're running the SQL Services on both servers as a domain user (which you'll need to in order to make this work - LocalSystem won't do it), here are the instructions you'll need:

http://technet.microsoft.com/en-us/library/bb735885.aspx

Remember that the user will need an SPN for both servers, but not the client - for example, if you are going from client -> server1 -> server2, the SQL Service account will need an SPN for both server1 and server2.

If you're confused (it's a confusing process), post a comment and I'll clarify the instructions.

rwmnau