2010-11-04 23 views
0

在Sql Server 2008 R2中,我有一個名爲Emp的表,並且我試圖在更新後更新事務(外部tran)中的一些值在提交之前,我開始了另一個事務,在我嘗試從同一個表(Emp)中選擇數據,但是通過一個環回鏈接服務器。 TSQL的是這樣的:在一個針對回送鏈接服務器的事務中的select語句永遠不會停止

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內部環回?
  • 查詢永不停止,有什麼想法?

回答

0

回答您的問題:

  1. 不,你不能以這種方式舊值;你會被阻止(見#2),否則你會得到新的值。

  2. 查詢從未停止的原因是因爲您阻止了自己(從技術上說,您正在使自己陷入僵局)。您的外部事務對該行持有鎖(實際上是頁),因此環回查詢將被阻止,直到更新鎖定被釋放。你可能(但不應該)在你的環回查詢中指定WITH(NOLOCK),但實際上它會返回更新但未提交的行。

如果你想在你的查詢舊值使用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