3

有人可以告诉我是否可以从一个过程中调用另一个过程,并且如果任一过程的任何部分失败,则将所有内容回滚?

如果这是可能的,有人可以给我看一个如何实现的小例子吗?

编辑:过程“b”失败,但过程“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;
4

1 回答 1

1

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

如何检测 MySQL 存储过程中的回滚?

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

编辑:

我认为正在发生的是内部 SP COMMIT 或 ROLLBACK 影响外部 SP 事务。这段代码对我有用,如果内部 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();

于 2012-10-10T19:44:04.290 回答