针对环回链接服务器的事务中的select语句永远不会停止

时间:2010-11-04 18:46:00

标签: database tsql transactions

在Sql Server 2008 r2中,我有一个名为Emp的表,我正在尝试更新事务中的一些值(外部tran),现在更新之后和提交之前,我开始另一个事务,在女巫我尝试从同一个表(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内部进行环回吗?
  • 查询从不停止,任何想法?

1 个答案:

答案 0 :(得分:0)

回答你的问题:

  1. 不,你不能以这种方式得到旧的价值观;你会被阻止(见#2)或者你会得到新的价值。

  2. 查询永远不会停止的原因是因为你阻塞了自己(从技术上讲,你自己就是死锁。)你的外部事务正在锁定该行(实际上是页面),因此阻止了环回查询直到更新锁定被释放。您可以(但不应该)在您的环回查询中指定WITH(NOLOCK)但实际上会返回更新但未提交的行。

  3. 如果希望查询中的OLD值使用OUTPUT子句。 http://msdn.microsoft.com/en-us/library/ms177564.aspx

    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