【问题标题】:sql server: managing transactions (begin, save, commit, rollback) across multiple stored proceduressql server:跨多个存储过程管理事务(开始、保存、提交、回滚)
【发布时间】:2014-05-20 07:31:03
【问题描述】:

在 T-Sql 中,rollback transaction 回滚除指定保存点名称之外的所有事务。要仅回滚部分修改,我们使用rollback transaction @save_point_name。那是 save transaction @save_point_name 必须在前面说明。如果引用的保存点已经回滚(从事务日志中删除),则会引发错误。同样,如果没有活动事务,则需要声明begin transaction @transaction_name,并且可以以相同的方式回滚。这样可以快速发现错误或使用try...catch 机制。

rollback 不同,commit transaction @transaction_name 完全忽略其@transaction_name 部分并仅执行提交,或者减少@@trancount 或结束事务。所以没有办法知道或指定哪个(嵌套)事务,或者就此而言 - 一个保存点,正在(伪)提交。我知道事务最初并不意味着嵌套,因此存在保存点。

一种典型的方法是,在每个过程中,检查@@trancount 以确定是创建保存点还是开始新事务。然后稍后,确认确定,检查事务状态并相应地提交或回滚(或什么都不做)。

这种检查是很多样板文件,尤其是当您有很多程序调用(多个)程序时,所有这些程序都只会在出现问题时回滚自己的操作。所以我的尝试是抽象事务,以便人们可以简单地编写类似这样的内容。

create procedure RollBackOnlyMyActions
as
declare @SavePointName nvarchar(32) = N'RollBackToHere';
begin try
    exec CreateSavePoint @SavePointName;    

    --do stuff

    --call other procedures that may roll back only its actions

    --do other stuff

    exec CommitSavePoint @SavePointName;
end try
begin catch
    exec RollBackSavePoint @SavePointName;
end catch

在哪里(让我打印出来)

create procedure dbo.CreateSavePoint
    @SavePointName nvarchar(32)
as
declare @Msg nvarchar(255);
print N'Preparing to create save point ['+@SavePointName+N'].';
print N'Checking not in an uncommitable transaction.';
if xact_state() != -1 
begin 
    print N'Not in an uncommitable transaction. Checking for transaction existence.';
    if @@TranCount = 0
    begin
        print N'No active transaction. Starting a new one.';
        begin transaction @SavePointName;
    end
    else
    begin
        print N'In active transaction. Saving transaction point.';
        save transaction @SavePointName;
    end
end
else
begin
    print N'In an uncommitable transaction. No use saving. Throwing exeption.';
    set @Msg = N'Uncommitable transaction.';
    throw 50000,@Msg,1;
end
go

create procedure dbo.CommitSavePoint
    @SavePointName nvarchar(32)
as
declare @Msg nvarchar(255);
print N'Preparing to commit save point ['+@SavePointName+N'].';
print N'Checking not in an uncommitable transaction.';
if xact_state() != -1
begin
    print N'Not in an uncommitable transaction. Checking transaction count.';
    if @@trancount > 1
    begin
        print N'In nested transaction of '+convert(nvarchar(255),@@trancount)+N'. Committing once.';
    end
    else if @@trancount = 1
    begin
        print N'In outter transaction. Committing.';        
    end
    else
    begin
        print N'No active transaction. Throw exception.';
        set @Msg = N'No transaction to commit.';
        throw 50000,@Msg,1;
    end
    commit transaction;
end
else
begin
    print N'In an uncommitable transaction. Cannot commit. Throwing exeption.';
    set @Msg = N'Uncommitable transaction.';
    throw 50000,@Msg,1;
end
go

create procedure dbo.RollbackSavePoint
    @SavePointName nvarchar(32)
as
declare @Msg nvarchar(255);
print N'Prepare to rollback savepoint ['+@SavePointName+N']';
print N'Checking not in an uncommitable transaction.';
if xact_state() != -1 
begin 
    print N'Not in an uncommitable transaction. Trying rollback';
    begin try
        rollback transaction @SavePointName;
    end try
    begin catch
        print N'Something went wrong. Rethrowing exception.';
        throw;
    end catch
end
else
begin
    print N'In an uncommitable transaction. No use rolling back. Throwing exeption.';
    set @Msg = N'Uncommitable transaction.';
    throw 50000,@Msg,1;
end
go

这没用。当我得到一个

Msg 266, Level 16, State 2, Procedure CreateSavePoint, Line 0
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.

在第一次调用 CreateSavePoint 之后。也就是说,似乎 sql server 不喜欢跨多个过程管理事务。

所以。是否有任何解决方法,例如抑制此错误的方法?还是我在这里遗漏了一个重要概念?

【问题讨论】:

    标签: tsql stored-procedures transactions savepoints


    【解决方案1】:

    回滚问题可以通过使用 SET XACT_ABORT ON 解决,它是“自动回滚”(简单)并抑制错误 266。

    【讨论】:

      猜你喜欢
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-04
      • 1970-01-01
      • 2020-10-13
      • 1970-01-01
      相关资源
      最近更新 更多