前段時(shí)間筆者在做一個(gè)BizTalk Server 2006的項(xiàng)目,使用SQL Adapter時(shí)碰到“分布式事務(wù)已完成。請(qǐng)將此會(huì)話登記到新事務(wù)或 NULL 事務(wù)中”的錯(cuò)誤。
筆者使用的操作系統(tǒng)為Windows Server 2003企業(yè)版 + SP2。數(shù)據(jù)庫(kù)管理系統(tǒng)使用SQL Server 2005企業(yè)版 + SP2。BizTalk Server 使用2006企業(yè)版,通過(guò)BizTalk生成項(xiàng)向?qū)мD(zhuǎn)換存儲(chǔ)過(guò)程為Xml Schema,在部署的時(shí)候由BizTalk SQL Adapter通過(guò)指定對(duì)應(yīng)Xml Namespace來(lái)訪問(wèn)該存儲(chǔ)過(guò)程。BizTalk Server 和 SQL Server 部署在不同的服務(wù)器上。各服務(wù)器不在Windows域中,配置各臺(tái)服務(wù)器的MSDTC,設(shè)置“事務(wù)管理器通信”為“不要求進(jìn)行驗(yàn)證”。
查了一下MSDN文檔,屬于“MSSQLSERVER_8525”數(shù)據(jù)庫(kù)引擎錯(cuò)誤。MSDN描述了在什么樣的情況下會(huì)碰到“MSSQLSERVER_8525”錯(cuò)誤。
將分布式事務(wù)處理協(xié)調(diào)器與 SQL Server 配合使用的編程模型需要應(yīng)用程序顯式登記到分布式事務(wù)或從中脫離出來(lái)。
滿足以下四個(gè)條件時(shí)會(huì)出現(xiàn)此錯(cuò)誤:
1.應(yīng)用程序已登記到分布式事務(wù)中。
2.無(wú)論原因如何,該事務(wù)已結(jié)束(已提交或回滾)。
3.用戶應(yīng)用程序并未顯式地從分布式事務(wù)中脫離或顯式地登記到新的分布式事務(wù)中。
4.應(yīng)用程序嘗試執(zhí)行任何脫離現(xiàn)有分布式事務(wù)或登記到新的分布式事務(wù)以外的事務(wù)操作,如發(fā)出查詢或啟動(dòng)本地事務(wù)。
錯(cuò)誤狀態(tài) 1 在應(yīng)用程序執(zhí)行創(chuàng)建本地事務(wù)的操作時(shí)使用,狀態(tài) 2 在應(yīng)用程序嘗試登記到綁定會(huì)話時(shí)使用。
MSDN說(shuō)明了相關(guān)用戶操作。應(yīng)用程序登記到分布式事務(wù)中之后,應(yīng)用程序必須顯式地從分布式事務(wù)中脫離或登記到另一個(gè)分布式事務(wù)中。這樣將從上一個(gè)登記的事務(wù)中隱式脫離。有關(guān)從分布式事務(wù)脫離或登記到其中的準(zhǔn)確語(yǔ)法,請(qǐng)參見(jiàn)該應(yīng)用程序的編程接口手冊(cè)。
更多的內(nèi)容可以訪問(wèn)http://technet.microsoft.com/zh-cn/library/bb326310.aspx。
BizTalk SQL適配器訪問(wèn)的SQL Server存儲(chǔ)過(guò)程大概的內(nèi)容描述如下:
通過(guò)存儲(chǔ)過(guò)程傳入多個(gè)參數(shù),更新數(shù)據(jù)到指定數(shù)據(jù)表中,然后把操作成功或失敗的結(jié)果通過(guò) FOR XML AUTO,ELEMENTS語(yǔ)句返回給SQL適配器。對(duì)于數(shù)據(jù)表的更新操作上同事使用“BEGIN TRAN”來(lái)開(kāi)啟一個(gè)事務(wù)。問(wèn)題就出在存儲(chǔ)過(guò)程添加的事務(wù)上。
在BizTalk項(xiàng)目中,筆者使用了Orchestration來(lái)訪問(wèn)SQL適配器,對(duì)于Orchestration的設(shè)置為“長(zhǎng)期事務(wù)”,而訪問(wèn)SQL適配器的一部分功能塊放在了一個(gè)作用域中,對(duì)該作用域設(shè)置為“原子事務(wù)”。對(duì)BizTalk應(yīng)用程序進(jìn)行部署后出現(xiàn)上面提到的錯(cuò)誤。
問(wèn)題解決。由于存儲(chǔ)過(guò)程是同事按SQL 2000的方式來(lái)寫的,筆者第一想到的就是使用SQL Server 2005中T-SQL語(yǔ)句新功能——TRY/CATCH塊帶代替。TRY CATCH結(jié)構(gòu)就是類似于C#語(yǔ)言中的那種經(jīng)典結(jié)構(gòu)。關(guān)于TRY/CATCH的使用建議看一下“使用 TRY/CATCH 語(yǔ)句解決 SQL Server 2005 死鎖”。
以下是部分SQL片段:
BEGIN TRY
BEGIN TRANSACTION;
--更新語(yǔ)句
COMMIT TRANSACTION;
SET @ReutrnValue = ’01’;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION;
END
END CATCH;
在存儲(chǔ)過(guò)程的最后返回XML:
SELECT Code AS ReturnValue FROM ManifestStatus Manifest
WHERE Code = @ReutrnValue
FOR XML AUTO,ELEMENTS
簡(jiǎn)單分析。出現(xiàn)“分布式事務(wù)已完成。請(qǐng)將此會(huì)話登記到新事務(wù)或 NULL 事務(wù)中”錯(cuò)誤是在數(shù)據(jù)庫(kù)這一層處理出現(xiàn),在BizTalk Server 的業(yè)務(wù)流程中發(fā)起了一個(gè)分布式事務(wù),而該分布式事務(wù)調(diào)用的存儲(chǔ)過(guò)程剛好又包含自己的事務(wù)。在網(wǎng)上搜索了一下,在程序調(diào)試過(guò)程中訪問(wèn)SQL Server出現(xiàn)該錯(cuò)誤還是比較常見(jiàn)。
筆者使用的操作系統(tǒng)為Windows Server 2003企業(yè)版 + SP2。數(shù)據(jù)庫(kù)管理系統(tǒng)使用SQL Server 2005企業(yè)版 + SP2。BizTalk Server 使用2006企業(yè)版,通過(guò)BizTalk生成項(xiàng)向?qū)мD(zhuǎn)換存儲(chǔ)過(guò)程為Xml Schema,在部署的時(shí)候由BizTalk SQL Adapter通過(guò)指定對(duì)應(yīng)Xml Namespace來(lái)訪問(wèn)該存儲(chǔ)過(guò)程。BizTalk Server 和 SQL Server 部署在不同的服務(wù)器上。各服務(wù)器不在Windows域中,配置各臺(tái)服務(wù)器的MSDTC,設(shè)置“事務(wù)管理器通信”為“不要求進(jìn)行驗(yàn)證”。
查了一下MSDN文檔,屬于“MSSQLSERVER_8525”數(shù)據(jù)庫(kù)引擎錯(cuò)誤。MSDN描述了在什么樣的情況下會(huì)碰到“MSSQLSERVER_8525”錯(cuò)誤。
將分布式事務(wù)處理協(xié)調(diào)器與 SQL Server 配合使用的編程模型需要應(yīng)用程序顯式登記到分布式事務(wù)或從中脫離出來(lái)。
滿足以下四個(gè)條件時(shí)會(huì)出現(xiàn)此錯(cuò)誤:
1.應(yīng)用程序已登記到分布式事務(wù)中。
2.無(wú)論原因如何,該事務(wù)已結(jié)束(已提交或回滾)。
3.用戶應(yīng)用程序并未顯式地從分布式事務(wù)中脫離或顯式地登記到新的分布式事務(wù)中。
4.應(yīng)用程序嘗試執(zhí)行任何脫離現(xiàn)有分布式事務(wù)或登記到新的分布式事務(wù)以外的事務(wù)操作,如發(fā)出查詢或啟動(dòng)本地事務(wù)。
錯(cuò)誤狀態(tài) 1 在應(yīng)用程序執(zhí)行創(chuàng)建本地事務(wù)的操作時(shí)使用,狀態(tài) 2 在應(yīng)用程序嘗試登記到綁定會(huì)話時(shí)使用。
MSDN說(shuō)明了相關(guān)用戶操作。應(yīng)用程序登記到分布式事務(wù)中之后,應(yīng)用程序必須顯式地從分布式事務(wù)中脫離或登記到另一個(gè)分布式事務(wù)中。這樣將從上一個(gè)登記的事務(wù)中隱式脫離。有關(guān)從分布式事務(wù)脫離或登記到其中的準(zhǔn)確語(yǔ)法,請(qǐng)參見(jiàn)該應(yīng)用程序的編程接口手冊(cè)。
更多的內(nèi)容可以訪問(wèn)http://technet.microsoft.com/zh-cn/library/bb326310.aspx。
BizTalk SQL適配器訪問(wèn)的SQL Server存儲(chǔ)過(guò)程大概的內(nèi)容描述如下:
通過(guò)存儲(chǔ)過(guò)程傳入多個(gè)參數(shù),更新數(shù)據(jù)到指定數(shù)據(jù)表中,然后把操作成功或失敗的結(jié)果通過(guò) FOR XML AUTO,ELEMENTS語(yǔ)句返回給SQL適配器。對(duì)于數(shù)據(jù)表的更新操作上同事使用“BEGIN TRAN”來(lái)開(kāi)啟一個(gè)事務(wù)。問(wèn)題就出在存儲(chǔ)過(guò)程添加的事務(wù)上。
在BizTalk項(xiàng)目中,筆者使用了Orchestration來(lái)訪問(wèn)SQL適配器,對(duì)于Orchestration的設(shè)置為“長(zhǎng)期事務(wù)”,而訪問(wèn)SQL適配器的一部分功能塊放在了一個(gè)作用域中,對(duì)該作用域設(shè)置為“原子事務(wù)”。對(duì)BizTalk應(yīng)用程序進(jìn)行部署后出現(xiàn)上面提到的錯(cuò)誤。
問(wèn)題解決。由于存儲(chǔ)過(guò)程是同事按SQL 2000的方式來(lái)寫的,筆者第一想到的就是使用SQL Server 2005中T-SQL語(yǔ)句新功能——TRY/CATCH塊帶代替。TRY CATCH結(jié)構(gòu)就是類似于C#語(yǔ)言中的那種經(jīng)典結(jié)構(gòu)。關(guān)于TRY/CATCH的使用建議看一下“使用 TRY/CATCH 語(yǔ)句解決 SQL Server 2005 死鎖”。
以下是部分SQL片段:
BEGIN TRY
BEGIN TRANSACTION;
--更新語(yǔ)句
COMMIT TRANSACTION;
SET @ReutrnValue = ’01’;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION;
END
END CATCH;
在存儲(chǔ)過(guò)程的最后返回XML:
SELECT Code AS ReturnValue FROM ManifestStatus Manifest
WHERE Code = @ReutrnValue
FOR XML AUTO,ELEMENTS
簡(jiǎn)單分析。出現(xiàn)“分布式事務(wù)已完成。請(qǐng)將此會(huì)話登記到新事務(wù)或 NULL 事務(wù)中”錯(cuò)誤是在數(shù)據(jù)庫(kù)這一層處理出現(xiàn),在BizTalk Server 的業(yè)務(wù)流程中發(fā)起了一個(gè)分布式事務(wù),而該分布式事務(wù)調(diào)用的存儲(chǔ)過(guò)程剛好又包含自己的事務(wù)。在網(wǎng)上搜索了一下,在程序調(diào)試過(guò)程中訪問(wèn)SQL Server出現(xiàn)該錯(cuò)誤還是比較常見(jiàn)。