我遇到類似問題The current transaction cannot be committed and cannot support operations that write to the log file,但我有後續問題。SQL事務錯誤:無法提交當前事務並且不能支持寫入日誌文件的操作
有引用Using TRY...CATCH in Transact-SQL,我會回來的第二個答案...
我的代碼(繼承,當然)具有簡化形式:
SET NOCOUNT ON
SET XACT_ABORT ON
CREATE TABLE #tmp
SET @transaction = 'insert_backtest_results'
BEGIN TRANSACTION @transaction
BEGIN TRY
--do some bulk insert stuff into #tmp
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION @transaction
SET @errorMessage = 'bulk insert error importing results for backtest '
+ CAST(@backtest_id as VARCHAR) +
'; check backtestfiles$ directory for error files ' +
' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) +
' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
' error_state ' + CAST(ERROR_STATE() AS VARCHAR) +
' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
RAISERROR(@errorMessage, 16, 1)
RETURN -666
END CATCH
BEGIN TRY
EXEC usp_other_stuff_1 @whatever
EXEC usp_other_stuff_2 @whatever
-- a LOT of "normal" logic here... inserts, updates, etc...
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION @transaction
SET @errorMessage = 'error importing results for backtest '
+ CAST(@backtest_id as VARCHAR) +
' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) +
' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
' error_state ' + CAST(ERROR_STATE() AS VARCHAR) +
' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
RAISERROR(@errorMessage, 16, 1)
RETURN -777
END CATCH
RETURN 0
我想我有足夠的信息來玩弄它並自己弄清楚......不幸的是,再現錯誤證明是不可能的。所以我希望在這裏詢問將有助於澄清我對問題和解決方案的理解。
此存儲過程,間歇性,拋象這樣的錯誤之一:
error importing results for backtest 9649 error_number: 3930 error_message: The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction. error_severity: 16 error_state 1 error_line: 217
如此明顯的錯誤是從第二個catch塊
基於我在Using TRY...CATCH in Transact-SQL讀過來,我想想發生了什麼事情,當拋出異常時,使用XACT_ABORT
導致事務被「終止並回滾」......然後BEGIN CATCH
的第一行盲目地試圖再次回滾。
我不知道爲什麼原開發商啓用XACT_ABORT
,所以我想更好的解決方案(將其刪除)是使用XACT_STATE()
只回滾,如果有一個交易(<>0
)。這聽起來合理嗎?我錯過了什麼嗎?
此外,提及登錄錯誤消息讓我懷疑:是否有另一個問題,可能與配置?在這種情況下,我們是否使用RAISEERROR()
來解決問題?在記錄不可能的情況下,是否記錄了錯誤信息?
您的模板假定try塊內的事務;我們在1個事務中有多個try塊。 –
@Adam:這是關於如何處理'XACT_STATE'和CATCH塊中的事務。您可以使用這個模板在一個事務中擁有多個try塊。這個想法是瞭解事務和catch塊如何相互作用,並且作爲獎勵,您還可以處理嵌套事務和savepoints,這在批處理中非常有用,因爲它可以恢復批處理的其餘部分,即使只有一個進入失敗了。 –
我已經提前將回滾語句包裝在一個'if XACT_STATE()<> 0'中,但只有時間會告訴我們是否爲我們解決了這個問題。猜猜我會繼續,現在接受你的答案。 –