У меня проблема, аналогичная Текущая транзакция не может быть принята и не может поддерживать операции, которые записывают в файл журнала , но у меня есть дополнительный вопрос.
Ответ там содержит ссылки Использование TRY ... CATCH в 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
Итак, очевидно, что ошибка исходит из 2-го блока catch
Основываясь на том, что я прочитал в Используя TRY ... CATCH в Transact-SQL , я думаю, что при возникновении исключения используется XACT_ABORT
вызывает «завершение и откат» транзакции ... и затем первая строка BEGIN CATCH
пытается вслепую откатить снова.
Я не знаю, почему первоначальный разработчик включил XACT_ABORT
, поэтому я думаю, что лучшим решением (чем его удаление) было бы использование XACT_STATE()
для отката только при наличии транзакции (<>0
). Это звучит разумно? Я что-то упустил?
Кроме того, упоминание о регистрации в сообщении об ошибке заставляет меня задуматься: есть ли другая проблема, возможно, с конфигурацией? Способствует ли использование RAISEERROR()
в этом сценарии этой проблеме? Регистрируется ли это, в каком-то случае, когда регистрация невозможна, так как на это ссылается сообщение об ошибке?