Точки сохранения транзакции

Точки сохранения предоставляют механизм отката части транзакций. Для создания точек сохранения служит инструкция SAVE TRANSACTION savepoint_name. Затем при помощи инструкции ROLLBACK TRANSACTION savepoint_name транзакцию можно откатить не до начала, а только до точки сохранения.

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

Следующий пример демонстрирует использование точки сохранения в системе заказов, где вероятность отсутствия товаров на складе крайне мала, поскольку компания работает с хорошими поставщиками и пунктами повторного заказа. Обычно приложение должно проверять наличие товара на складе, прежде чем принять заказ. В этом примере предполагается, что по каким-то причинам проверка наличия товара на складе — относительно дорогая операция (например, из-за подключения по медленной модемной линии или глобальной сети). Приложение можно построить таким образом, чтобы оно выполняло обновление и при возникновении ошибки (товар отсутствует на складе) откатывало его назад. В этом случае быстрая проверка параметра @@ERROR после вставки строки может выполняться значительно быстрее, чем проверка количества товара перед обновлением.

Таблица InvCtrl имеет ограничение CHECK, которое вызывает ошибку 547, если значение в столбце QtyInStk становится меньше 0. Процедура OrderStock создает точку сохранения. При возникновении ошибки 547 она откатывает транзакцию до точки сохранения и возвращает оставшееся количество товаров вызывающему процессу. После этого вызывающий процесс может принять заказ на имеющееся количество товара. Если процедура OrderStock возвращает 0, вызывающий процесс понимает, что на складе имеется достаточное количество товаров.

SET NOCOUNT OFF;
GO
USE AdventureWorks;
GO
CREATE TABLE InvCtrl
    (WhrhousID      int,
    PartNmbr      int,
    QtyInStk      int,
    ReordrPt      int,
    CONSTRAINT InvPK PRIMARY KEY
    (WhrhousID, PartNmbr),
    CONSTRAINT QtyStkCheck CHECK (QtyInStk > 0) );
GO
CREATE PROCEDURE OrderStock
    @WhrhousID int,
    @PartNmbr int,
    @OrderQty int
AS
    DECLARE @ErrorVar int;
    SAVE TRANSACTION StkOrdTrn;
    UPDATE InvCtrl SET QtyInStk = QtyInStk - @OrderQty
        WHERE WhrhousID = @WhrhousID
        AND PartNmbr = @PartNmbr;
    SELECT @ErrorVar = @@error;
    IF (@ErrorVar = 547)
    BEGIN
        ROLLBACK TRANSACTION StkOrdTrn;
        RETURN (SELECT QtyInStk
                FROM InvCtrl
                WHERE WhrhousID = @WhrhousID
                AND PartNmbr = @PartNmbr);
    END
    ELSE
        RETURN 0;
GO

См. также

Другие ресурсы

ROLLBACK TRANSACTION (Transact-SQL)
SAVE TRANSACTION (Transact-SQL)

Справка и поддержка

Получение помощи по SQL Server 2005