Вложенные хранимые процедуры, содержащие шаблон ОТКАТА ВЫГОДЫ ПОПЫТКИ?

Я интересуюсь побочными эффектами и потенциальными проблемами следующего шаблона:

CREATE PROCEDURE [Name]
AS
BEGIN
    BEGIN TRANSACTION
    BEGIN TRY
        [...Perform work, call nested procedures...]
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION
        RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
    END CATCH
END

В меру моего понимания этого шаблона является звуковым при использовании с единственной процедурой - процедура или завершит все свои операторы без ошибки, или это будет откатывать все действия и сообщать об ошибке.

Однако, когда одна хранимая процедура называет другую хранимую процедуру, чтобы сделать некоторое подразделение работы (с пониманием, что меньшую процедуру иногда называют самостоятельно), я вижу, что проблема появляется с отношением к откатам - информационное сообщение (Уровень 16) выпущено, указав The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.. Это, которое я принимаю, - то, потому что откат в подпроцедуре всегда откатывает наиболее удаленную транзакцию, не только транзакцию, запущенную в подпроцедуре.

Я действительно хочу все это откатываемое и прерванное, если какая-либо ошибка происходит (и ошибка, о которой сообщают клиенту как ошибка SQL), я просто не уверен во всех побочных эффектах, которые прибывают из внешних слоев, пытающихся откатывать транзакцию, которая уже откатывалась. Возможно, проверка @@TRANCOUNT прежде, чем сделать откат на каждом уровне TRY CATCH?

Наконец существует клиентский конец (Linq2SQL), который имеет свой собственный слой транзакции:

try
{
    var context = new MyDataContext();
    using (var transaction = new TransactionScope())
    {       
            // Some Linq stuff
        context.SubmitChanges();
        context.MyStoredProcedure();
        transactionComplete();
    }
}
catch
{
    // An error occured!
}

Если хранимая процедура, "MySubProcedure", названный в MyStoredProcedure, повышают ошибку, я могу быть уверен, что все ранее сделанное в MyStoredProcedure будет откатываться, все операции Linq, сделанные SubmitChanges, будут откатываться, и наконец что ошибка будет зарегистрирована? Или что делает я должен измениться в своем шаблоне, чтобы гарантировать, что целая операция является атомарной, все еще позволяя дочерним частям использоваться индивидуально (т.е. подпроцедуры должен все еще иметь ту же атомарную защиту),

54
задан David 15 January 2010 в 08:04
поделиться

2 ответа

Это наш шаблон (журнал ошибок удален)

Он предназначен для обработки

Пояснения:

  • все TXN начинаются и фиксируются/откатываются в паре так, чтобы @@TRANCOUNT совпадали при входе и выходе

  • несовпадения @@TRANCOUNT вызывали ошибку 266, так как

    • BEGIN TRAN инкременты @@TRANCOUNT

    • COMMIT постановления @@TRANCOUNT

    • ROLLBACK возвращает @@TRANCOUNT к нулю

  • Вы не можете декрементировать @@TRANCOUNT для текущего диапазона
    . Можно подумать, что "внутренняя транзакция"

  • SET XACT_ABORT ON подавляет ошибку 266, вызванную несовпадением @@TRANCOUNT
    , а также решает такие проблемы, как эта "SQL Server Transaction Timeout" на dba.se

  • Это позволяет использовать TXN на стороне клиента (например, LINQ). Одна хранимая процедура может быть частью распределенной или XA-транзакции, или просто одной, инициированной в коде клиента (например, .net TransactionScope)

Использование:

  • Каждый хранимый proc должен соответствовать одному и тому же шаблону

Summary

  • Так что не создавайте больше TXN, чем вам нужно

The code

CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT

    IF @starttrancount = 0
        BEGIN TRANSACTION

       [...Perform work, call nested procedures...]

    IF @starttrancount = 0 
        COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
        ROLLBACK TRANSACTION;
    THROW;
    --before SQL Server 2012 use 
    --RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO

Notes:

  • Проверка отката на самом деле избыточна из-за SET XACT_ABORT ON. Однако, от этого мне становится легче, без этого выглядит странно, и допускает ситуации, когда на

  • Remus Rusanu имеется аналогичная оболочка , использующая точки сохранения. Я предпочитаю атомарный вызов БД и не использую частичные обновления, как в их статье

106
ответ дан 7 November 2019 в 07:53
поделиться

Я не первый парень (и не является Эрланд), но он написал абсолютные Библии на обработке ошибок. За пределами осложнений LINQ может добавить к своей проблеме, все ваши другие вопросы следует ответить здесь:

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

(Старая ссылка: http : ///www.sommarskog.se/error_handling_2005.html )

11
ответ дан 7 November 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: