首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 8525 引擎錯誤排查:分散式事務已完成,請登記新事務 — BizTalk + SQL Adapter 實戰案例

     編輯:關於SqlServer

BizTalk Server 2006 透過 SQL Adapter 呼叫含交易的預存程序,遇到 MSSQLSERVER_8525:「分散式事務已完成。請將此會話登記到新事務或 NULL 事務中」。本文記錄環境、錯誤觸發條件、根因分析 (巢狀事務 + 死鎖回滾) 與解決方案 (TRY/CATCH 替代舊式交易控制)。

環境

  • OS: Windows Server 2003 Ent + SP2
  • DB: SQL Server 2005 Ent + SP2
  • BizTalk: 2006 Ent,Orchestration 長期事務 + 原子事務範圍
  • 跨機器部署,非網域,MSDTC 設定「不要求驗證」

錯誤觸發四條件 (MSDN)

  1. 應用程式已登記分散式事務。
  2. 該事務已結束 (Commit/Rollback)。
  3. 應用程式未顯式脫離或登記新分散式事務。
  4. 應用程式嘗試執行脫離現有分散式事務外的操作 (查詢、啟動本地事務)。

狀態 1 = 建立本地事務時觸發;狀態 2 = 登記綁定會話時觸發。

根因分析

  • BizTalk 發起分散式事務 (DTO) → 呼叫 SQL Adapter → 執行預存程序。
  • 預存程序使用舊式 BEGIN TRAN ... COMMIT/ROLLBACK 開啟本地事務,在 DTO 內形成巢狀事務。
  • 發生 Deadlock → SQL Server 選擇犧牲者 Rollback 內層本地事務 → 外層 DTO 仍視為 Active。
  • 後續程式碼繼續執行 SQL (如回傳 XML) → 觸發 8525:當前會話仍關聯已結束的 DTO,卻嘗試執行新操作。

解決方案:TRY/CATCH 替代舊式交易控制 (SQL 2005+)

CREATE PROC usp_UpdateManifest
  @params ...
AS
BEGIN
  DECLARE @ReturnValue VARCHAR(2) = '99';
  BEGIN TRY
    BEGIN TRANSACTION;
      -- 更新邏輯
      UPDATE ... SET ... WHERE ...;
    COMMIT TRANSACTION;
    SET @ReturnValue = '01';
  END TRY
  BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    SET @ReturnValue = '99';
    -- 可選:記錄 ERROR_NUMBER/MESSAGE 到日誌表
  END CATCH;

  -- 統一回傳 XML (無論成敗)
  SELECT Code AS ReturnValue FROM ManifestStatus WHERE Code = @ReturnValue
  FOR XML AUTO, ELEMENTS;
END;

關鍵點

  • TRY/CATCH 確保交易要么完整 Commit,要么完整 Rollback,避免半開放狀態。
  • 外層 BizTalk DTO 仍需正確完成/中止;建議在 Orchestration 例外處理中呼叫 Rollback。
  • 並發死鎖仍可能發生,需配合索引優化、鎖升級控制、死鎖重試邏輯 (客戶端捕獲 1205 重試)。

參考

MSDN: MSSQLSERVER_8525 | TRY/CATCH

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved