Когда необходимо проверить @@trancount> 0 в try catch block?
Иногда я видел следующий фрагмент кода. Когда требуется if @@trancount > 0
с begin try
? Оба из них? Или это безопасный способ (лучшая практика) проверять его всегда, если он откатывается перед проверкой?
begin tran
begin try
... just several lines of sql ...
if @@trancount > 0 commit tran
end try
begin catch
if @@trancount > 0 rollback tran
end catch
Ответы
Ответ 1
Я могу подумать о нескольких сценариях, которые следует учитывать при работе с @@trancount
:
- Текущая транзакция вызывается из другой хранимой процедуры, которая
его собственная транзакция
- Текущая транзакция вызывается некоторым кодом .NET со своим собственным
сделка
- Текущая транзакция является единственной транзакцией
Я считаю, что Remus Rusanu Обработка исключений и вложенные транзакции обрабатывает все эти возможности.
Ответ 2
когда вы не используете @@trancount, сообщение об ошибке хранимой процедуры вложенной транзакции не возвращает точную причину ошибки, а просто возвращается "Запрос транзакции отката не имеет соответствующей начальной транзакции", в противном случае он дает точную причину ошибки, поэтому его легко обработать ошибку с правильным синтаксисом.
Ответ 3
причина проверки в том, что если вы фиксируете trans или откатываете его, когда @@trancount = 0, вы получаете исключение с таким сообщением об ошибке: Запрос COMMIT TRANSACTION не имеет соответствующей BEGIN TRANSACTION.
Ответ 4
Чтобы ответить на вопрос - пора сделать @@trancount, если посередине кода потенциально мог уже выполнить фиксацию или откат транзакции, которую вы начали. Так что, если вы, например, вызываете хранимые процедуры, выполните проверки в конце.
Между прочим, вместо того, чтобы делать if @@trancount> 0, я бы посоветовал лучше проверить @@trancount в начале вашего блока кода, а затем посмотреть, увеличилось ли число к концу, и в этом случае сделать фиксация или откат, в зависимости от try/catch.
Особенно, если вы находитесь в триггере, потому что @@trancount всегда будет равен 1, поэтому простое выполнение @@trancount> 0 может вызвать ошибку.
Но даже если ваш код находится только в хранимой процедуре, предположительно, он был вызван другой процедурой, которая сама имеет открытую транзакцию, если ваш код ошибается и откатывается, то внешней хранимой процедуре также будет откатываться транзакция (см. Https://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2630-nested-transactions-are-real/).
Так
НАЧАТЬ ТРАНСПОРТ @@TRANCOUNT
НАЧАТЬ ТРАНСПОРТ @@TRANCOUNT
ROLLBACK TRAN PRINT @@TRANCOUNT
показывает 1 2 0
Так что в основном - если код посередине вызывает другие процедуры, вам нужно выполнить проверку IF @@TRANCOUNT.