Напишите хранимую процедуру, чтобы в случае сбоя одного оператора он не влиял на другой? - PullRequest
0 голосов
/ 04 ноября 2019

У меня есть эта процедура, которая в основном вставляет данные.

    Begin Transaction
                Insert into [dbo].Values
                    (
                        EQ



                    )
                    values 
                    (
                        @EQ


                    )

                  End

            --Set @STATUSRet= 'Created'
            --Set @ErrorRet= ''

        Commit Transaction
    End Try
    Begin Catch

        Set @STATUSRet= 'Failed'
        Set @ErrorRet= (Select ERROR_MESSAGE())

        Rollback Transaction

    End Catch

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

1 Ответ

2 голосов
/ 04 ноября 2019

Метод управления транзакциями по умолчанию: auto-commit :

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

Таким образом, если две вставки не обернуты в явную транзакцию, это будет поведение. Если у вас есть больше блоков кода, вы можете использовать два отдельных блока явных транзакций, таких как:

DECLARE @ExecuteSecondTransaction BIT = 0;

-- local database
BEGIN TRY

    BEGIN TRANSACTION;

        -- CODE BLOCK GOES HERE

        SET @ExecuteSecondTransaction = 1;

    COMMIT TRANSACTION;

END TRY
BEGIN CATCH 

   IF @@TRANCOUNT > 0
   BEGIN
      ROLLBACK TRANSACTION
   END;

   -- GET ERRORS DETAILS OR THROW ERROR

END CATCH;

-- remote database
IF @ExecuteSecondTransaction = 1
BEGIN

    BEGIN TRY

        BEGIN TRANSACTION;
        -- CODE BLOCK GOES HERE
        COMMIT TRANSACTION;

    END TRY
    BEGIN CATCH 

       IF @@TRANCOUNT > 0
       BEGIN
          ROLLBACK TRANSACTION
       END;

       -- GET ERRORS DETAILS OR THROW ERROR

    END CATCH;

END;
...