Database 针对环回链接服务器的事务中的select语句从不停止

Database 针对环回链接服务器的事务中的select语句从不停止,database,tsql,transactions,Database,Tsql,Transactions,在Sql Server 2008 r2中,我有一个名为Emp的表,我正在尝试更新事务外部传输中的一些值,现在在更新之后和提交之前,我开始了另一个事务,在该事务中,我尝试从同一个表Emp中选择数据,但是通过环回链接服务器。 tsql如下所示: USE MASTER GO EXEC sp_addlinkedserver @server = N'loopback',@srvproduct=N'',@provider = N'SQLNCLI', @datasrc = @@SERVERNAME,@ca

在Sql Server 2008 r2中,我有一个名为Emp的表,我正在尝试更新事务外部传输中的一些值,现在在更新之后和提交之前,我开始了另一个事务,在该事务中,我尝试从同一个表Emp中选择数据,但是通过环回链接服务器。 tsql如下所示:

USE MASTER

GO

EXEC sp_addlinkedserver @server = N'loopback',@srvproduct=N'',@provider = N'SQLNCLI', @datasrc = @@SERVERNAME,@catalog = 'MstrDtl'
GO

EXEC sp_serveroption loopback,N'remote proc transaction promotion','FALSE'

Go

create SYNONYM loopy FOR loopback.MstrDtl.dbo.Emp


use MstrDtl
BEGIN TRAN OuterTran
      BEGIN
      update table dbo.Emp set Salary = 123456 where Name='abcdx'
            BEGIN TRAN InnerTran
                  select Salary from loopy where Name = 'abcdx'
            COMMIT TRAN InnerTran
            ROLLBACK TRAN OuterTran
      END
所以我有两个问题:

我可以用这种方法在查询中更新受影响的行以在InnerTran中回送旧值吗? 问题永远不会停止,知道吗?
回答您的问题:

不,您不能以这种方式获取旧值;您将被阻止,请参见2,否则将获得新值

查询从未停止的原因是,您在技术上封锁了自己,使自己陷入僵局。您的外部事务实际上持有该行页面上的锁,因此在释放更新锁之前,环回查询将被阻止。您可以但不应该在环回查询中指定WITH NOLOCK,但这将实际返回已更新但未提交的行

如果要在查询中使用旧值,请使用OUTPUT子句

CREATE TABLE #emp
(
    id INT IDENTITY PRIMARY KEY CLUSTERED,
    empName VARCHAR(255),
    salary MONEY
)
go

INSERT INTO #emp(empName, salary) 
SELECT 'bill', 5000
UNION ALL 
SELECT 'ted', 5000
UNION ALL 
SELECT 'cheech', 35000
UNION ALL 
SELECT 'chong', 15000
UNION ALL 
SELECT 'tango', 70000
UNION ALL 
SELECT 'Cash', 200000

GO

DECLARE @oldValues TABLE
(
    id INT,
    empname VARCHAR(255),
    salary money
)


UPDATE #emp SET salary = salary + 500
OUTPUT DELETED.* INTO @oldValues
WHERE  empName = 'bill'

SELECT E.empName, E.salary AS NewSalary, O.salary AS OldSalary
FROM #emp E
    INNER JOIN @oldValues O 
        ON E.id = O.id 

DROP TABLE #emp