Mysql嵌套事务与回滚

时间:2012-10-10 19:37:49

标签: mysql

有人可以告诉我是否可以从一个程序中调用另一个程序,如果任何一个程序的任何部分都失败了,那么回滚一切?

如果可以,有人可以告诉我一个如何实现这个的小例子吗?

编辑:过程“b”失败,但过程“a”仍然在表“a”中插入一行。我的理解是,如果插入的任何部分失败,那么所有(两个插入)都会回滚,而这里没有发生。问题是为什么不呢?

程序“a”

BEGIN
  DECLARE b INT DEFAULT 0;
  DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
  DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;

  START TRANSACTION;
    INSERT INTO a(a)
    VALUES(iA);

     CALL b(iB,LAST_INSERT_ID(),@b);
     SELECT @b INTO b;

     IF b !=1 THEN
        ROLLBACK;
      ELSE
        COMMIT;
  END IF;
END

程序“b”

BEGIN
  DECLARE b INT DEFAULT 0;
  DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
  DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;

  START TRANSACTION;
    INSERT INTO b VALUES(iB,id);
    SET b=1;
  COMMIT;
END;

1 个答案:

答案 0 :(得分:1)

您需要在两个过程中处理事务,但是调用另一个过程的proc应该检查返回值并根据它回滚它的事务。这是内部过程的一个例子:

How to detect a rollback in MySQL stored procedure?

然后,您将检查p_return_code并回滚父事务。

  

编辑:

我认为发生的是内部SP COMMIT或ROLLBACK影响外部SP TRANSACTION。这段代码对我有用,如果内部SP失败,它会回滚两个插入语句。首先调用ab()工作,插入新用户记录并插入新游戏记录,如果我们从游戏表中删除记录并再次运行ab(),因为用户ID已经存在,它回滚游戏表插入:

create procedure ab()
BEGIN
  START TRANSACTION;
    INSERT INTO games (title) VALUES ('bad game');
    CALL ba(@ret);
    IF @ret!=0 THEN
      ROLLBACK;
    ELSE
      COMMIT;
    END IF;
END;


create procedure ba(OUT return_value tinyint unsigned)
BEGIN
  DECLARE exit handler for sqlexception
  BEGIN
    set return_value = 1;
  END;

  INSERT INTO users (id) VALUES(1);
  set return_value = 0;
END;

测试使用call ab();