MySQL事务难题

标签 mysql exception transactions handler

我需要在单个原子事务中执行多个插入。例如:

start transaction;

insert ...

insert ...

commit;

然而,当 MySQL 遇到错误时,它只会中止导致错误的特定语句。例如,如果第二个插入语句中有错误,提交仍将发生并且第一个插入语句将被记录。因此,当错误发生时,MySQL 事务并不是真正的事务。为了克服这个问题,我使用了一个错误退出处理程序来回滚事务。现在交易默默地中止了,但我不知道是什么问题。

所以这是你的难题:

如何让 MySQL 在遇到错误时中止事务,并将错误代码传递给调用者?

最佳答案

How can I both make MySQL abort a transaction when it encounters an error, and pass the error code on to the caller?

MySQL确实将错误代码传递给调用者,并且基于此错误代码,调用者可以自由决定是否要提交目前已完成的工作(忽略此特定 INSERT 语句的错误)或回滚事务。

这不同于 PostgreSQL它总是在出错时中止事务,这种行为是许多问题的根源。

更新:

使用无条件 ROLLBACK 是一种不好的做法在存储过程中。

存储过程是可堆叠的,而事务不是,所以 ROLLBACK在嵌套存储过程中将回滚到事务的最开始,而不是存储过程执行的状态。

如果您想使用事务来恢复错误时的数据库状态,请使用 SAVEPOINT构造和 DECLARE HANDLER回滚到保存点:

CREATE PROCEDURE prc_work()
BEGIN
        DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK TO sp_prc_work;
        SAVEPOINT sp_prc_work;
        INSERT  …;
        INSERT  …;
        …
END;

任一插入失败都将回滚过程所做的所有更改并退出。

关于MySQL事务难题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4547592/

相关文章:

php - SQL : Merge two rows by some ID and keep values

MySQL 表创建错误(语法对我来说很好)

java - hibernate 中的异常(一对一)

Delphi XE8 在应用程序启动时优雅地处理 ETetheringException

sql - 没有进入 Catch block

mysql - MySql 存储过程中的事务

asp.net - 如何在.net core框架中使用TransactionScope?我找不到它

mysql - 单条记录按主键更新慢

jquery - Codeigniter 使从 php 创建的 html 表可点击

Java 未检查的异常从 main 中抛出