【发布时间】:2011-11-21 05:39:28
【问题描述】:
我遇到了与The current transaction cannot be committed and cannot support operations that write to the log file 类似的问题,但我有一个后续问题。
那里的答案引用了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
我认为我有足够的信息来使用它并自己解决它......不幸的是,重现错误几乎是不可能的。所以我希望在这里提问有助于澄清我对问题和解决方案的理解。
这个存储过程会间歇性地抛出类似这样的错误:
回测导入结果错误 9649 error_number: 3930 error_message: 当前事务无法提交,无法支持写入日志文件的操作。回滚事务。 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() 是否会导致问题?是否会像错误消息所暗示的那样在某种无法记录的情况下记录下来?
【问题讨论】:
标签: sql-server sql-server-2005 transactions