Как я могу гарантировать, что вложенные транзакции совершаются независимо друг от друга? - PullRequest
8 голосов
/ 06 января 2011

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

Другими словами, если первые два выполненияЕсли вложенная процедура выполнена успешно, но третья не удалась, возможно ли сохранить результаты первых двух выполнений (и не откатить их)?

У меня есть хранимая процедура, определенная примерно так в SQL Server2000:

CREATE PROCEDURE toplevel_proc ..
AS
BEGIN

         ...

         while @row_count <= @max_rows
    begin
        select @parameter ... where rownum = @row_count 
        exec nested_proc @parameter
        select @row_count = @row_count + 1
    end

END

Ответы [ 2 ]

8 голосов
/ 06 января 2011

Во-первых, в SQL Server не существует такой вещи, как вложенная транзакция

Тем не менее, вы можете использовать SAVEPOINTs согласно этому примеру (слишком долго, чтобы воспроизвести здесь, извините) от другого пользователя SO Remus Rusanu

Редактировать: Алексей Кузнецов упомянул (хотя и удалил свой ответ), что это не сработает, если транзакция обречена. Это может произойти с SET XACT_ABORT ON или некоторыми ошибками триггера.

4 голосов
/ 06 января 2011

С BOL:

СДЕЛКА ROLLBACK без имени_симпойнта или имя-транзакции выполняет откат к началу транзакции.При вложении транзакций этот же оператор откатывает все внутренние транзакции к самому внешнему оператору BEGIN TRANSACTION.

Я также обнаружил следующее из другого потока здесь :

Помните, что транзакции SQL Server на самом деле не являются вложенными, как вы думаете.После запуска явной транзакции последующий BEGIN TRAN увеличивает @@ TRANCOUNT, в то время как COMMIT уменьшает значение.Вся внешняя транзакция фиксируется, когда COMMIT приводит к нулю @@ TRANCOUNT.Но ROLLBACK без точки сохранения откатывает всю работу, включая внешнюю транзакцию.

Если вам нужно поведение вложенных транзакций, вам нужно будет использовать SAVE TRANSACTION вместо BEGIN TRAN и использовать ROLLBACK TRAN [savepoint_name] вместо ROLLBACK TRAN.

Таким образом, это будет выглядетьвозможно.

...