mysql中的事务控制:BEGIN、COMMIT与ROLLBACK

9次阅读

mysql事务需先设autocommit=0再BEGIN(等价于START TRANSACTION),否则ROLLBACK无效;不支持嵌套事务,仅能用SAVEPOINT实现部分回滚;COMMIT/ROLLBACK后事务结束,后续操作需重新开启。

mysql中的事务控制:BEGIN、COMMIT与ROLLBACK

MySQL 中的 BEGINCOMMITROLLBACK 是手动控制事务的核心语句,但它们**不保证自动开启事务**——是否真正进入事务状态,取决于当前会话的 autocommit 设置。

autocommit 关闭才是事务生效的前提

MySQL 默认开启 autocommit=1,此时每条 DML 语句(如 INSERTUPDATE)都会立即提交,BEGIN 后执行的语句仍可能被自动提交,导致 ROLLBACK 失效。

  • 必须先执行 SET autocommit = 0,再用 BEGIN(或 START TRANSACTION)显式开启事务
  • BEGIN 本身不是 SQL 标准关键字,在 MySQL 中是 START TRANSACTION 的同义词,但不带任何隐式设置作用
  • 某些客户端(如 phpMyAdmin、MySQL Workbench)可能默认关闭 autocommit,但脚本或连接池中往往不会,不能依赖

COMMIT 和 ROLLBACK 的边界很明确

事务从 BEGIN(或 START TRANSACTION)开始,到 COMMITROLLBACK 结束。之后的语句不属于该事务,也不会被回滚。

  • COMMIT 后,所有修改永久写入磁盘(受存储引擎和刷盘策略影响),无法撤销
  • ROLLBACK 仅能回滚当前未提交事务中的修改;如果中间执行过 COMMIT,之前已提交的部分不可逆
  • 执行 ROLLBACK 后,事务结束,后续语句需重新 BEGIN 才能再次开启事务

嵌套事务在 MySQL 中不存在

MySQL 不支持真正的嵌套事务。BEGIN 后再写一个 BEGIN,不会创建子事务,而是被忽略或报错(取决于版本和 SQL 模式)。

  • 想实现“部分回滚”,只能靠 SAVEPOINT:例如 SAVEPOINT sp1ROLLBACK TO sp1
  • SAVEPOINT 不会结束事务,ROLLBACK TO 后仍可继续 COMMITROLLBACK
  • 注意 SAVEPOINT 名称不能重复,否则后一次会覆盖前一次

常见误用场景与示例

下面这段代码在 autocommit=1 下运行,ROLLBACK 实际无效:

SET autocommit = 1; BEGIN; INSERT INTO users(name) VALUES('Alice'); ROLLBACK;

正确写法应为:

SET autocommit = 0; BEGIN; INSERT INTO users(name) VALUES('Alice'); UPDATE accounts SET balance = balance - 100 WHERE id = 1; COMMIT;

或者更稳妥地,用标准语法并显式控制:

SET autocommit = 0; START TRANSACTION; INSERT INTO users(name) VALUES('Bob'); DELETE FROM logs WHERE created_at < NOW() - INTERVAL 7 DAY; COMMIT;

最容易被忽略的是:应用层连接(如 pythonpymysqljavaConnection)通常默认开启 autocommit,且事务状态不跨请求保持——每次 http 请求都得自己重置 autocommit 并管理 BEGIN/COMMIT/ROLLBACK

text=ZqhQzanResources