T-SQL錯誤3930
(2010-10-04 01:35:10)
下一個
一大早遇上個問題:幫其他TEAM開發的一個SP,運行出錯。報的錯誤信息是:
メッセージ 3930、レベル 16、狀態 1、行 xx 。現在のトランザクションのコミットおよびログ ファイルに書き込む操作は サポートできません。(The current transaction cannot be committed and cannot support operations that write to the log file.)
原本已經調試通過的程序,代碼應該不會有問題。一查出錯的行數,那一行代碼居然是:COMMIT TRANSACTION,很稀罕的錯誤。再一檢查運行的環境,隻有登陸的用戶名與開發、調試時使用的不同,初步估計與用戶權限設定有關。
網上與error3930有關的信息很少,微軟的聯機幫助也語焉不詳。好不容易查到一篇文檔,說報這個錯時,XACT_STATE()的值一定是-1(正常時為1)。
再查XACT_STATE()的幫助文檔,發現一條有價值的說明,這個error與try...catch有關。這時猛想起程序中調用一個共通的函數,是別的TEAM以前開發的、沿用至今。這個共通函數又調用其他的子函數,多層嵌套的調用,業務邏輯很複雜,從沒花過氣力去研究它,但依稀記得其中正是用了很多的try...catch。
再查try...catch的幫助文檔,果然其中有關於COMMIT不能的情形的說明。當try的過程當中發生了事務不得不中止的情況時,事務就變成了不能COMMIT的狀態。本來這可能會引起程序Abort,但由於catch的存在,程序跳轉到catch部分處理,而catch部分隻是設置了錯誤信息、然後返回,並沒有進一步拋出例外、引起主程序的異常中止,使得主程序按照正常處理、執行到COMMIT,從而引起了3930錯誤。
按照以上的理解,用定位XACT_STATE()值變成-1的時間點的辦法進行排錯,很快找到了隱藏在幾層子函數調用下的問題點:對某一個其他DB裏的被查詢的表,沒有足夠的訪問權限。
メッセージ 916、レベル 14、狀態 1、行 1
現在のセキュリティ コンテキストでは、サーバー プリンシパル "XXX" はデータベース "XXX" にアクセスできません。
這個916錯誤,才是被catch給“吃掉”了的真正的錯誤信息。