【发布时间】:2020-07-08 17:12:52
【问题描述】:
这是我的存储过程:
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
谢谢:)
【问题讨论】:
-
看看我对 sqlexecepotions stackoverflow.com/a/60351232/5193536987654321@的回答
-
谢谢,这绝对很有趣。所以你认为这可能是当前 MySQL Server 版本中的一个 Bug 吗?但是我在第二次插入中导致异常的原因是,在配置为 NOT NULL 的列中将其中一个值设置为 null。我想说这并不是一个特殊的例外,但可能是最常见的例外之一。你真的认为连这个异常都没有得到正确处理吗?
-
触发器中的代码可能会导致提交,因为第一个
INSERT上的触发器将在第二个INSERT之前运行 -
因为并非所有错误都会触发 sqlexecption,这取决于错误发生的位置。所以得到正确的数字,然后像我在第二个代码块中那样编程
-
@Nick Ohh 这对我来说很有意义。有什么办法可以防止这种情况发生吗?我将尝试在我的过程中明确设置自动提交。但我想这无济于事,因为它不应该对交易产生影响。还有其他建议吗?