Это хорошая идея, чтобы обработать повторную блокировку тупика из блока catch хранимой процедуры - PullRequest
10 голосов
/ 26 сентября 2011

Насколько я понимаю, невозможно полностью предотвратить блокировку транзакции.

Я хотел бы иметь транзакцию, которая никогда не завершится в зависимости от кода приложения. Итак, я видел этот шаблон в использовании для Microsoft SQL, и мне интересно, если это хорошая идея?


    DECLARE @retry  tinyint
    SET @retry  = 5
    WHILE @retry >0
    BEGIN
      BEGIN TRANSACTION
      BEGIN TRY
        // do transaction her
        COMMIT
        BREAK
      END TRY
      BEGIN CATCH
        ROLLBACK

        if (ERROR_NUMBER() = 1205 OR ERROR_NUMBER() = 1222)
        BEGIN
          SET @retry = @retry - 1
          IF @retry = 0
             RAISEERROR('Could not complete transaction',16,1);
          WAITFOR DELAY '00:00:00.05' -- Wait for 50 ms
          CONTINUE
        END
        ELSE
        BEGIN
          RAISEERROR('Non-deadlock condition encountered',16,1);
          BREAK;
        END
      END CATCH;
    END

Ответы [ 2 ]

7 голосов
/ 26 сентября 2011

Реализация, которую вы имеете, является , а не хорошей идеей, поскольку она слепо повторяет попытку, не обнаруживая фактическую ошибку.Например, если ошибка была тайм-аутом, вы могли бы в конечном итоге связать соединение в 5 раз с превышением времени ожидания, не решая ничего.

Гораздо лучший подход - обнаружить, что это ошибка 1205 -жертва тупика и повторите попытку только в этом случае.

Вы можете использовать:

IF ERROR_NUMBER() = 1205 

См. документацию для ERROR_NUMBER().

6 голосов
/ 26 сентября 2011

Логика повторения для исправляемых ошибок должна быть в коде клиента.

Для взаимоблокировок MSDN заявляет, что там это делается

Если вы повторите попытку в SQL, то выможет в конечном итоге ударить CommandTimeout.

Есть и другие ошибки, поэтому вы можете написать общий обработчик

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...