事务启动后执行出错是否自动回滚?手动回滚方法咨询
关于MySQL事务中出错后的回滚问题
嘿,这个问题问到点子上了,我来给你理清楚细节:
一、默认情况下,出错会不会自动回滚到事务启动前?
答案是不一定,得分情况看:
- 首先得确保你的表用的是支持事务的存储引擎(比如InnoDB)——如果是MyISAM这种不支持事务的引擎,那事务根本不起作用,每个操作都是即时提交的,出错了也没法回滚。
- 假设用的是InnoDB:
- 如果是单个语句执行失败(比如INSERT违反主键约束、UPDATE触发了数据校验错误这类真·执行失败,找不到匹配行不算错误哈),这个出错的语句会被回滚,但事务不会自动终止,后面的INSERT/UPDATE还会继续执行。最后如果执行COMMIT,那些成功的操作都会被提交,只有出错的那个操作被撤销,并不会回到
START TRANSACTION之前的初始状态。 - 只有遇到致命错误(比如数据库崩溃、连接突然断开),整个事务才会被自动回滚到启动前的状态。
- 如果是单个语句执行失败(比如INSERT违反主键约束、UPDATE触发了数据校验错误这类真·执行失败,找不到匹配行不算错误哈),这个出错的语句会被回滚,但事务不会自动终止,后面的INSERT/UPDATE还会继续执行。最后如果执行COMMIT,那些成功的操作都会被提交,只有出错的那个操作被撤销,并不会回到
举个直观例子:你执行START TRANSACTION; INSERT INTO TABLE1 ...; UPDATE TABLE1 ...(这里出错); UPDATE TABLE2 ...; COMMIT;,那INSERT是成功的,UPDATE TABLE1被回滚,UPDATE TABLE2成功,最后COMMIT后,TABLE1有新增的数据,TABLE2有更新的数据,TABLE1的UPDATE没生效——并不是回到事务启动前的空状态。
二、怎么手动回滚到事务启动前的初始状态?
如果你想在任何一个操作出错时,把所有操作都撤销,回到事务启动前的样子,需要这么做:
- 一旦检测到某个SQL执行出错,立刻执行
ROLLBACK;语句,不要继续执行后面的操作,也不要执行COMMIT。 - 举个实际的操作流程:
START TRANSACTION; -- 执行第一个INSERT INSERT INTO TABLE1 ...; -- 检查是否出错,如果出错就回滚(程序里要加错误判断逻辑) -- 执行UPDATE TABLE1 UPDATE TABLE1 ...; -- 发现出错,立即执行回滚 ROLLBACK; -- 这样所有操作都回到启动前的状态 - 如果是在MySQL的存储过程里,还可以设置错误处理程序,自动捕获异常并回滚:
这样只要任何一步出错,存储过程就会自动触发ROLLBACK,直接回到事务启动前的初始状态。DELIMITER // CREATE PROCEDURE my_transaction() BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SELECT '事务执行失败,已回滚' AS result; END; START TRANSACTION; INSERT INTO TABLE1 ...; UPDATE TABLE1 ...; UPDATE TABLE2 ...; INSERT INTO TABLE3 ...; COMMIT; SELECT '事务执行成功' AS result; END // DELIMITER ;
总结一下
- 单个语句出错不会自动回滚整个事务,只会回滚出错的语句,后续操作仍会执行;只有致命错误才会自动全回滚。
- 要手动回到事务启动前的状态,在出错后立即执行
ROLLBACK;,不要执行COMMIT。
内容的提问来源于stack exchange,提问作者eulercode
相关产品推荐
相关产品推荐

