“MSSQLSERVER_8525”SQL Server資料庫引擎錯誤
作者:鄭佐日期:2007-8-31 前段時間筆者在做一個BizTalk Server 2006的項目,使用SQL Adapter時碰到“分散式交易已完成。請將此會話登記到新事務或 NULL 事務中”的錯誤。 筆者使用的作業系統為Windows Server 2003企業版 + SP2。資料庫管理系統使用SQL Server 2005企業版 + SP2。BizTalk Server 使用2006企業版,通過BizTalk產生項嚮導轉換預存程序為Xml Schema,在部署的時候由BizTalk SQL Adapter通過指定對應Xml Namespace來訪問該預存程序。BizTalk Server 和 SQL Server 部署在不同的伺服器上。各伺服器不在Windows域中,配置各台伺服器的MSDTC,設定“交易管理員通訊”為“不要求進行驗證”。 查了一下MSDN文檔,屬於“MSSQLSERVER_8525”資料庫引擎錯誤。MSDN描述了在什麼樣的情況下會碰到“MSSQLSERVER_8525”錯誤。將分散式交易協調器與 SQL Server 配合使用的編程模型需要應用程式顯式登記到分散式交易或從中脫離出來。 滿足以下四個條件時會出現此錯誤:1.應用程式已登記到分散式交易中。 2.無論原因如何,該事務已結束(已提交或復原)。3.使用者應用程式並未顯式地從分散式交易中脫離或顯式地登記到新的分散式交易中。4.應用程式嘗試執行任何脫離現有分散式交易或登記到新的分散式交易以外的事務操作,如發出查詢或啟動本地事務。 錯誤狀態 1 在應用程式執行建立本地事務的操作時使用,狀態 2 在應用程式嘗試登記到綁定會話時使用。 MSDN說明了相關使用者操作。應用程式登記到分散式交易中之後,應用程式必須顯式地從分散式交易中脫離或登記到另一個分散式交易中。這樣將從上一個登記的事務中隱式脫離。有關從分散式交易脫離或登記到其中的準確文法,請參見該應用程式的編程介面手冊。更多的內容可以訪問http://technet.microsoft.com/zh-cn/library/bb326310.aspx。
BizTalk SQL適配器訪問的SQL Server預存程序大概的內容描述如下:
通過預存程序傳入多個參數,更新資料到指定資料表中,然後把操作成功或失敗的結果通過 FOR XML AUTO,ELEMENTS語句返回給SQL適配器。對於資料表的更新操作上同事使用“BEGIN TRAN”來開啟一個事務。問題就出在預存程序添加的事務上。 在BizTalk項目中,筆者使用了Orchestration來訪問SQL適配器,對於Orchestration的設定為“長期事務”,而訪問SQL適配器的一部分功能塊放在了一個範圍中,對該範圍設定為“原子事務”。對BizTalk應用程式進行部署後出現上面提到的錯誤。 由於預存程序是同事按SQL 2000的方式來寫的,筆者第一想到的就是使用SQL Server 2005中T-SQL語句新功能——TRY/CATCH塊帶代替。TRY CATCH結構就是類似於C#語言中的那種經典結構。關於TRY/CATCH的使用建議看一下“使用 TRY/CATCH 語句解決 SQL Server 2005 死結”。以下是部分SQL片段:BEGIN TRY BEGIN TRANSACTION; --更新語句 COMMIT TRANSACTION; SET @ReutrnValue = '01';END TRYBEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN ROLLBACK TRANSACTION; ENDEND CATCH; 在預存程序的最後返回XML:
SELECT Code AS ReturnValue FROM ManifestStatus Manifest
WHERE Code = @ReutrnValueFOR XML AUTO,ELEMENTS 結果對於單條資料的處理不會再出現該提示,不過對於並發執行過程中,發現有死結復原現象。可能語句的其它地方寫的有問題。 簡單分析。出現“分散式交易已完成。請將此會話登記到新事務或 NULL 事務中”錯誤是在資料庫這一層處理出現,在BizTalk Server 的商務程序中發起了一個分散式交易,而該分散式交易調用的預存程序剛好又包含有自己的事務,那該事務就變成了內嵌事務。在出現DeadLock的情況下,會RollBACK所有事務。在網上搜尋了一下,在程式調試過程中訪問SQL Server出現該錯誤還是比較常見。