有人可以告诉我是否可以从一个程序中调用另一个程序,如果任何一个程序的任何部分都失败了,那么回滚一切?
如果可以,有人可以告诉我一个如何实现这个的小例子吗?
编辑:过程“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;
答案 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();