事务需显式commit/rollback,自动提交默认开启;长事务危害大;隔离级别、锁机制与索引共同决定并发行为。

事务提交和回滚必须显式调用 COMMIT 或 ROLLBACK
MySQL 默认开启自动提交(autocommit=1),每条 SQL 语句单独成事务,执行完立刻生效。一旦你用 BEGIN 或 START TRANSACTION 手动开启事务,后续所有 DML 操作都不会写入磁盘,直到你明确执行 COMMIT —— 否则连接断开、服务重启或客户端异常退出,都会触发隐式 ROLLBACK。
常见错误是以为“执行完 UPDATE 就算改好了”,结果忘了 COMMIT,导致数据看似成功却没持久化;或者在异常处理里只捕获错误但没写 ROLLBACK,留下脏数据。
-
SET autocommit = 0会全局禁用自动提交,但不推荐——容易遗忘恢复,建议只在事务块内用BEGIN显式控制 - 存储过程中不能直接用
COMMIT/ROLLBACK,除非加CONTAINS SQL且未开启autocommit,否则报错ERROR 1305 (42000): SAVEPOINT does not exist - DDL 语句(如
ALTER TABLE)在大多数引擎中会隐式触发COMMIT,导致前面未提交的 DML 一并提交——这是很多线上误操作的根源
并发控制靠隔离级别 + 行锁,不是靠“事务开始时间”
MySQL 的可重复读(REPEATABLE READ)不是靠锁住整张表,而是基于 MVCC(多版本并发控制) + 当前读(SELECT ... FOR UPDATE)组合实现。同一事务中多次 SELECT 看到相同快照,但若执行了 UPDATE 或加锁查询,就会触发当前读,可能看到其他事务已提交的新数据。
很多人误以为设了 REPEATABLE READ 就能避免幻读,其实不然:普通 SELECT 不会看到新插入行,但 INSERT ... SELECT 或 UPDATE ... WHERE 范围匹配时仍可能遇到间隙锁(Gap Lock)引发的幻读现象。
- 查看当前会话隔离级别:
SELECT @@transaction_isolation - InnoDB 中
READ COMMITTED级别下,每次SELECT都生成新快照,适合高并发读多写少场景;但无法避免不可重复读 - 唯一能完全避免幻读的是
SERIALIZABLE,但它会把所有普通SELECT转成SELECT ... LOCK IN SHARE MODE,性能代价极大,极少在线上使用
FOR UPDATE 和 LOCK IN SHARE MODE 锁行为差异极大
SELECT ... FOR UPDATE 对扫描到的索引记录加排他锁(X 锁),其他事务无法对该记录做任何修改或加任何锁;而 SELECT ... LOCK IN SHARE MODE 加的是共享锁(S 锁),允许其他事务加 S 锁,但会阻塞 X 锁。两者都遵循“只锁命中索引”,没走索引就是全表锁——这点极易被忽略。
典型踩坑:WHERE 条件字段没索引,SELECT ... FOR UPDATE 实际锁住整个聚簇索引,导致并发更新严重阻塞,甚至死锁。
- 用
EXPLAIN确认查询是否走了索引,再决定是否加锁 -
FOR UPDATE在非唯一索引上可能触发间隙锁,锁住不存在但符合范围的“空档”,防止幻插入 - 事务中多个
FOR UPDATE顺序不一致(如 A 先锁 id=1 再锁 id=2,B 反过来),是死锁高频原因,应用层需约定统一加锁顺序
长事务是并发问题的放大器,不是解决方案
事务生命周期越长,MVCC 版本链越臃肿,undo log 占用空间越大,同时活跃事务越多,对 purge 线程压力越大,最终拖慢整体性能。线上常见“查不到刚插入的数据”,往往是因为一个长事务卡在那儿,让其他事务的可见性判断始终回退到旧快照。
更隐蔽的问题是:长事务期间,即使没做任何修改,也会阻止 binlog purging 和 undo log 回收,导致磁盘空间缓慢耗尽。
- 监控长事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW()) - TIME_TO_SEC(TRX_STARTED) > 60 - 应用代码中避免在事务内做 HTTP 请求、文件读写、sleep 等耗时操作
- 超时强制回滚可通过
innodb_lock_wait_timeout控制等待时长,但无法终止已运行中的长事务——得靠业务逻辑主动控制
事务的边界、锁的粒度、隔离级别的实际效果,三者交织在一起。真正难的不是记住概念,而是在具体 SQL 走什么索引、有没有覆盖、是否触发间隙锁、MVCC 快照怎么取这些细节里,做出准确预判。











