Откат транзакций по умолчанию при выключенном XACT_ABORT

У меня есть следующая транзакция

BEGIN TRAN
        DECLARE @TransactionAmount MONEY = 5.00
        UPDATE Account SET Balance -= @TransactionAmount WHERE AccountID = 1
        UPDATE Account SET Balance += @TransactionAmount WHERE AccountID = 'blah'
COMMIT TRAN

Как происходит сбой во втором UPDATE заявление (AccountID является int столбец), и все утверждение обернуто в TRAN блок, изменение в первой выписке откатывается, и остаток для AccountID 1 не вычитается.

Как нет ROLLBACK В приведенном выше коде кажется, что SQL-сервер выполняет откат автоматически, без необходимости явного ROLLBACK заявление

Когда я смотрел на это, кажется, что поведение автоматического отката контролируется настройкой под названием xact_abort,

Я нашел следующий скрипт онлайн, который распечатывает настройки, которые на

DECLARE @options INT
SELECT @options = @@OPTIONS

PRINT @options
IF ( (1 & @options) = 1 ) PRINT 'DISABLE_DEF_CNST_CHK' 
IF ( (2 & @options) = 2 ) PRINT 'IMPLICIT_TRANSACTIONS' 
IF ( (4 & @options) = 4 ) PRINT 'CURSOR_CLOSE_ON_COMMIT' 
IF ( (8 & @options) = 8 ) PRINT 'ANSI_WARNINGS' 
IF ( (16 & @options) = 16 ) PRINT 'ANSI_PADDING' 
IF ( (32 & @options) = 32 ) PRINT 'ANSI_NULLS' 
IF ( (64 & @options) = 64 ) PRINT 'ARITHABORT' 
IF ( (128 & @options) = 128 ) PRINT 'ARITHIGNORE'
IF ( (256 & @options) = 256 ) PRINT 'QUOTED_IDENTIFIER' 
IF ( (512 & @options) = 512 ) PRINT 'NOCOUNT' 
IF ( (1024 & @options) = 1024 ) PRINT 'ANSI_NULL_DFLT_ON' 
IF ( (2048 & @options) = 2048 ) PRINT 'ANSI_NULL_DFLT_OFF' 
IF ( (4096 & @options) = 4096 ) PRINT 'CONCAT_NULL_YIELDS_NULL' 
IF ( (8192 & @options) = 8192 ) PRINT 'NUMERIC_ROUNDABORT' 
IF ( (16384 & @options) = 16384 ) PRINT 'XACT_ABORT'

Тем не менее, при запуске на моем сервере, XACT_ABORT не отображается в распечатанном списке, поэтому не включен.

У меня вопрос: зачем нужна ROLLBACK Скажите, когда кажется, что SQL-сервер выполняет откат автоматически?

2 ответа

Решение

Если XACT_ABORT = OFF тогда это очень непредсказуемо, если транзакция откатывается или нет. SQL Server иногда этого не делает, иногда делает, а иногда даже прерывает пакет. (Да, это не имеет никакого смысла.) Другие возможные результаты включают обречение на транзакцию или разрыв соединения.

В вашем случае вы можете надежно использовать TRY-CATCH предотвратить откат и обработать исключение.

Я считаю хорошей практикой не полагаться на обработку ошибок, если это возможно. Вместо этого откатите транзакцию. Также вставьте обработку ошибок в клиент, если это возможно.

Если вы используете транзакции, рекомендуется установить XACT_ABORT = ON в начале вашей хранимой процедуры. Erland Sommarskog предлагает отличную информацию об обработке ошибок:

http://www.sommarskog.se/error_handling/Part1.html

Другие вопросы по тегам