繁体   English   中英

存储过程中的 MySQL 事务不会回滚

[英]MySQL Transaction in Stored Procedure does not ROLLBACK

这是我的存储过程:

CREATE PROCEDURE `procedureName`
(
    IN var1 VARCHAR(45),
    IN var2 VARCHAR(100),
    IN var3 VARCHAR(45),
    IN var4 DATE,
    IN someMoreVars VARCHAR(100)
)
COMMENT 'just a comment'
BEGIN
    DECLARE tempVar INT DEFAULT -1;

    DECLARE exit handler for sqlexception
      BEGIN
      SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'SQLError occured. Triggered ROLLBACK';
        -- ERROR
      ROLLBACK;
    END;

    DECLARE exit handler for sqlwarning
      BEGIN
      SIGNAL SQLSTATE '35000' SET MESSAGE_TEXT = 'SQLWarning occured. Triggered ROLLBACK';
        -- WARNING
      ROLLBACK;
    END;

    START TRANSACTION;
        INSERT INTO `schemaName`.`table1` (`column1`, `column2`, `moreColumns`)
            VALUES (var1, var2, moreVars);
        SELECT LAST_INSERT_ID() INTO tempVar;
        INSERT INTO `schemaName`.`table2` (`column1`, `column2`, `evenMoreColumns`)
            VALUES (tempVar, var3, var4);
    COMMIT;

END

为什么那个存储过程不回滚? 当我使用适用于第一次插入但在第二次插入时引发异常的参数时,此过程不会回滚,我最终在第一个表中得到数据,但在第二个表中没有数据。

我正在使用 InnoDB 引擎。

我已经使用 MySQL Workbench 测试了这种行为,并且由于它在 GUI 中内置了这种奇怪的自动提交行为,因此我还通过从 C# 脚本调用该过程对其进行了测试。

我还检查了文档中是否提到 LAST_INSERT_ID() 函数作为导致隐式提交的函数。 但是没有在列表中找到它。 或者该函数是否调用了另一个导致隐式提交的函数? 如果是,是否有任何解决方法? 我需要调用这个函数来使用它的 PRIMARY KEY 作为第二个表中的 FOREIGN KEY。 如果此信息有帮助:我也在使用触发器。

这是其中一张表的插入触发器(它们几乎在所有插入/更新/删除表中):

CREATE DEFINER = CURRENT_USER TRIGGER `schema`.`table1_AFTER_INSERT` AFTER INSERT ON `table1` FOR EACH ROW
BEGIN
    INSERT INTO `schema`.`table1_audit` (`table1_audit_action`, `table1_audit_timestamp`, `table1_audit_user`, `table1_val1`, `table1_some_more_columns`)
    VALUES ('insert', CURRENT_TIMESTAMP(), SESSION_USER(), NEW.table1_val1, NEW.table1_some_more_columns);
END

谢谢 :)

只是为了让这篇文章与最新信息保持同步:几天/几周前,我找到了一个解决方案来解决这个错误。

事实证明,问题是必须在“SIGNAL”之前调用“ROLLBACK”。 如果有人详细解释了为什么会这样,请随时添加该信息。 但是在发出异常信号后根本不可能回滚。 所以下面的代码应该可以工作:

DECLARE exit handler for sqlexception
BEGIN
    -- ERROR
  ROLLBACK;
  SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'SQLError occured. Triggered ROLLBACK';
END;

当然,SQLWarning 也是如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM