start transaction 是开启事务的推荐语句,begin 为其别名但易与 begin...end 混淆;commit 失效常见于非事务语句、ddl、连接断开或 autocommit=1;rollback 默认回退至事务起点,需 savepoint 实现部分回滚;长事务会阻塞并发并延长锁持有时间。

MySQL 事务开始用 BEGIN 还是 START TRANSACTION?
两者在功能上完全等价,BEGIN 是 START TRANSACTION 的别名,但官方文档明确建议优先用 START TRANSACTION。原因在于 BEGIN 容易和存储过程中的 BEGIN...END 块混淆,尤其在动态拼接 SQL 或 ORM 自动注入场景下可能引发歧义。
-
START TRANSACTION更语义清晰,明确表示“开启一个新事务” -
BEGIN在某些旧版客户端(如早期 phpMyAdmin)中可能被误解析为语句块起始 - 不支持嵌套事务:即使写两次
START TRANSACTION,MySQL 也只认最外层,内部的会被忽略
什么情况下 COMMIT 不会真正提交?
COMMIT 失效通常不是语句本身的问题,而是事务上下文已丢失或被隐式结束。常见于以下场景:
- 执行了非事务性语句(如
CREATE TABLE ... ENGINE=MyISAM),MySQL 会自动提交当前事务 - 执行了 DDL 语句(如
ALTER TABLE、DROP INDEX),InnoDB 会强制提交当前事务并开启新事务 - 连接异常断开(如超时、客户端崩溃),未
COMMIT的修改直接丢弃 - 使用了自动提交模式(
AUTOCOMMIT=1),单条 DML 语句执行完立即生效,COMMIT无实际作用
验证方式:执行 SELECT @@autocommit;,返回 0 表示手动提交模式启用。
ROLLBACK 能回退到任意中间点吗?
不能。MySQL 默认不支持多级回滚,ROLLBACK 总是回退到事务最开始的位置。若需部分回滚,必须配合 SAVEPOINT:
START TRANSACTION;
INSERT INTO users (name) VALUES ('Alice');
SAVEPOINT sp1;
INSERT INTO users (name) VALUES ('Bob');
SAVEPOINT sp2;
INSERT INTO users (name) VALUES ('Charlie');
ROLLBACK TO SAVEPOINT sp1; -- 只撤销 'Bob' 和 'Charlie'
COMMIT;-
SAVEPOINT名称区分大小写,且仅在当前事务内有效 - 回滚到某个
SAVEPOINT后,该点之后定义的其他SAVEPOINT自动失效 - 事务结束后所有
SAVEPOINT全部清除,无需手动释放
事务控制语句对锁和并发的影响
事务持续期间,InnoDB 会根据访问的数据行持有锁(如记录锁、间隙锁),这些锁直到 COMMIT 或 ROLLBACK 才释放。这意味着:
- 长事务(长时间未
COMMIT)会拖住锁,导致其他会话阻塞,甚至触发Lock wait timeout exceeded -
ROLLBACK操作本身可能很慢——它需要逆向执行所有已做的变更,尤其是涉及大量更新时 - 显式使用
START TRANSACTION后,哪怕只读查询(如SELECT)在可重复读(RR)隔离级别下也会加一致性读锁,影响并发性能
线上业务中,事务应尽量短小,避免在事务内做 HTTP 请求、文件读写等不可控耗时操作。










