Sql-Server

在連結伺服器上自動送出更新事務

  • June 6, 2018

我想了解更多關於在連結伺服器上執行跨伺服器查詢時自動送出事務在幕後發生的情況。

我天真地認為,在執行自動送出事務時,編譯器/SQL Server/其他東西只是在所有語句前面加上 aBEGIN TRANSACTION並在所有語句後面加上 a,COMMIT TRANSACTION因為所有內容在技術上都包含在事務中(總是創建事務是一種不好的做法嗎? ? )。我確信這是不正確的,並且我對為什麼執行跨伺服器UPDATE而不明確說明BEGIN TRANSACTION有效但明確說明不有效的原因感到困惑。根據微軟(https://docs.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql?view=sql-server-2017),一個明確BEGIN TRANSACTIONUPDATE引用連結伺服器上的表的查詢被升級為分佈式事務;並且由於未在連結伺服器上配置分佈式事務,因此我收到錯誤消息。自動送出設置如何避免這種情況?它如何不升級為分佈式事務?自動送出設置是否將數據發送到連結伺服器,但不會通過 Microsoft 分佈式事務協調器 (MS DTC) “偵聽”來自連結伺服器的響應;因此,如果發生錯誤,它會“默默地”失敗嗎?

自動送出不會升級為分佈式事務:

UPDATE l
SET l.RecordKey = s.RecordKey
FROM LinkedServer.ExampleDatabase.dbo.ExampleTable AS l
INNER JOIN ServerWithActiveConnection.ExampleDatabase.dbo.ExampleTable AS s
   ON l.Value1 = s.Value1;

顯式事務確實升級為分佈式事務(在我的情況下是錯誤):

BEGIN TRANSACTION
UPDATE l
SET l.RecordKey = s.RecordKey
FROM LinkedServer.ExampleDatabase.dbo.ExampleTable AS l
INNER JOIN ServerWithActiveConnection.ExampleDatabase.dbo.ExampleTable AS s
   ON l.Value1 = s.Value1;
COMMIT TRANSACTION;

我應該補充一點,這些語句是在 SQL Server Management Studio 中執行的。

鑑於連結伺服器是一個外部/單獨的連接,我希望它可以單獨處理/管理,就像通過SqlClient在 SQLCLR 中。作為一個單獨的連接,是否嘗試加入目前事務是可選的(這通過Enlist= {true | false}連接字元串關鍵字處理)。我猜is_remote_proc_transaction_promotion_enabled/“啟用RPC分佈式事務的提升”的連結伺服器屬性相當於Enlist連接字元串關鍵字。

話雖如此,有一些東西被忽略了(包括在我的原始答案中被忽略):該選項的名稱是“為 RPC啟用分佈式事務的提升”(強調我的)。突出顯示的部分在這里相當重要。此選項影響連結伺服器上的儲存過程呼叫,而不是正常的即席查詢批處理。因此,該選項不應與您在問題中描述的行為相關。

我的(受過教育的)猜測是,對於臨時查詢,目前事務中的“登記”選項預設為自動送出事務的“假”。但是,對於顯式事務,您是在告訴 SQL Server 中的所有語句都BEGIN TRAN ... COMMIT TRAN應該被視為原子操作,因此遠端連接會嘗試加入目前事務。

僅供參考:此行為與在 SSMS 中執行語句無關。那隻是一個將語句送出給 SQL Server 執行的客戶端。即使通過SQLCMD.EXESqlCient在 .NET 應用程序等中執行,它也應該是相同的行為。


更新

關於測試這一點,我建議 OP 使用 SQL Server Profiler 或擴展事件來擷取事務登記/提升到分佈式事務。OP回复說:

我遵循了您的建議並使用了 Profiler,當我使用顯式事務時,確實有一行EventClass具有“DTCTransaction”的EventSubClass值和“Enlisting in a DTC transaction”的值。當我依賴自動送出設置時,不存在這樣的行。

引用自:https://dba.stackexchange.com/questions/208923