如何使用try catch管理嵌套事务 [英] how to manage nested transaction with try catch

查看:219
本文介绍了如何使用try catch管理嵌套事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

--Drop Table Tab1

Begin Transaction TR1; 
Save Transaction TR1;
    Create Table Tab1(f1 decimal(10,0));
    Begin Transaction TR2
    Save Transaction TR2
        insert into Tab1 values(1);
        Begin Transaction TR3;
        Save Transaction TR3;
            insert into Tab1 values(2);
            Begin Try 
                insert into Tab1 values('OK');
                Commit Transaction TR3;
            END TRY
            BEGIN Catch
                print 'catch'
                RollBack Transaction TR3;
            End Catch

        insert into Tab1 values(3);
        Commit Transaction TR2
    insert into Tab1 values(4);
Commit Transaction TR1;
--Commit Transaction;
select * from Tab1;
Drop Table Tab1

Select @@TRANCount

错误发生:

信息3931,第16级,状态1,第17行 当前事务无法提交,也无法回滚到保存点.回滚整个交易.

Msg 3931, Level 16, State 1, Line 17 The current transaction cannot be committed and cannot be rolled back to a savepoint. Roll back the entire transaction.

如何处理.

推荐答案

出现某些类型的错误时,您将无法回滚到保存点.请参阅马丁史密斯的

When certain type of errors get raised you cannot rollback to a save point. See Martin Smith's answer to Rollback transaction to savepoint on failing ALTER TABLE … ADD CONSTRAINT. The way you detect this is to test Xact_state().

但是,您的问题有所不同,因为您还尝试使用嵌套事务.嵌套事务实际上并不像我们期望的那样在SQL中有效.

However your problem is somewhat different because you're also trying to use nested transactions. Nested transactions don't really work in SQL as we would expect them to.

例如,此操作失败,并显示Cannot roll back TR2. No transaction or savepoint of that name was found.

For example this fails with Cannot roll back TR2. No transaction or savepoint of that name was found.


    BEGIN TRANSACTION TR1; 
    BEGIN TRANSACTION TR2
    ROLLBACK TRANSACTION TR2
    COMMIT Transaction TR1

来自嵌套交易

  • SQL Server数据库引擎忽略提交内部事务

  • Committing inner transactions is ignored by the SQL Server Database Engine

ROLLBACK TRANSACTION语句的transaction_name参数引用一组命名嵌套事务的内部事务是不合法的. transaction_name只能引用最外层交易的交易名称

It is not legal for the transaction_name parameter of a ROLLBACK TRANSACTION statement to refer to the inner transactions of a set of named nested transactions. transaction_name can refer only to the transaction name of the outermost transaction

Paul S. Randal在

Paul S. Randal explores this further in A SQL Server DBA myth a day: (26/30) nested transactions are real

最好的办法是使用保存点",然后在捕获中以及最后检查Xact_state.

The best you can do is use Save points instead and check the Xact_state in your catch and at the end.

BEGIN TRANSACTION tr1; 

SAVE TRANSACTION tr2; 

CREATE TABLE tab1 
  ( 
     f1 DECIMAL(10, 0) 
  ); 

SAVE TRANSACTION tr3 

INSERT INTO tab1 
VALUES     (1); 

SAVE TRANSACTION tr4; 

INSERT INTO tab1 
VALUES     (2); 

BEGIN try 
    -- change the order of the follwoing two lines around to see the difference
    INSERT INTO tab1 VALUES (1 / 0); --Results in a rollback to savepoint
    INSERT INTO tab1 VALUES ('OK');  --Results in a complete rollback

    COMMIT TRANSACTION tr4; 
END try 

BEGIN catch 
    IF Xact_state() = -1 
      BEGIN 
          PRINT 'rollback transaction no other work can be done' 

          ROLLBACK TRANSACTION; 
      END 
    ELSE 
      BEGIN 
          PRINT 'rollback to savepoint' 

          ROLLBACK TRANSACTION tr4 
      END 
END catch 

IF Xact_state() > 0 
  BEGIN 
      INSERT INTO tab1 
      VALUES     (3); 

      INSERT INTO tab1 
      VALUES     (4); 

      COMMIT TRANSACTION tr1; 

      SELECT * 
      FROM   tab1; 

      DROP TABLE tab1 
  END 

这篇关于如何使用try catch管理嵌套事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆