我遇到类似问题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'中,但只有时间会告诉我们是否为我们解决了这个问题。猜猜我会继续,现在接受你的答案。 –