Подтвердить что ты не робот

Когда необходимо проверить @@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
4b9b3361

Ответ 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.