SQL Server Try Catch 異常捕捉


SQL Server Try Catch 異常捕捉

背景

今天遇到一個關於try catch 使用比較有意思的問題。如下一段代碼:

SELECT @@TRANCOUNT AS A BEGIN TRY BEGIN TRAN SELECT @@TRANCOUNT AS A1 INSERT INTO A2A ( ID1 ) VALUES ( 'A' ) COMMIT TRAN; END TRY BEGIN CATCH SELECT @@TRANCOUNT AS A2 ROLLBACK TRAN; SELECT ERROR_MESSAGE() AS ErrorMessage , ERROR_SEVERITY() AS ErrorSeverity , ERROR_STATE() AS ErrorState END CATCH SELECT @@TRANCOUNT AS B

第一次執行時,無法正常捕捉到錯誤,並執行catch的代碼,返回錯誤信息
這里寫圖片描述
第二次執行,就能正常捕捉。且后續再執行就都正常了。
這里寫圖片描述
同樣的代碼,執行2次出現完全不同的結果。這是很讓人費解的。

分析

首先 看第一次執行報錯,看這個錯誤的級別編號是16。
try catch 不能捕捉什么樣的錯誤

嚴重級別為 10 或更低的錯誤,屬於警告或信息性消息。
嚴重級別為 20 或更高且終止會話的 SQL Server 數據庫引擎任務處理的錯誤。此類問題過於嚴重數據庫引擎會直接終止會話。所以無法往后繼續執行。

總之,就是能捕捉嚴重級別大於10,且不會嚴重到之前終止會話的錯誤

關於嚴重級別 和 描述:
https://docs.microsoft.com/zh-cn/sql/relational-databases/errors-events/database-engine-error-severities?view=sql-server-2017 “數據庫引擎錯誤嚴重性”

那我們前面的例子錯誤級別16,的確是屬於可以捕捉的情況。那為什么會有這個問題。跟執行計划的產生有關系。因為你第一次執行的時候,SQL server 在需要編譯SQL 語句,產生執行計划。就是這個時候執行計划還沒有。所以他無法往下面繼續執行。就無法CATCH到。第二次,以及后面幾次再執行,因為已經緩存了執行計划。所以可以catch到。

我們執行完第一次之后可以查看對應的執行計划
這里寫圖片描述
然后再執行,就可以成功捕捉了。如果我們把執行計划清除掉
DBCC FREEPROCCACHE 或者使用option(recomplile)進行重編譯。那么結果就會是一直無法捕捉。
這里寫圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM