autocommit=1时DML执行完立即释放锁,因每条语句隐式开启并提交独立事务;autocommit=0时锁持续至COMMIT或ROLLBACK,且DDL总会隐式提交并不可回滚。

autocommit=1 时,DML 语句执行完立刻释放行锁
当 autocommit = 1(默认状态)时,每条 UPDATE、DELETE、INSERT 都会隐式开启并立即提交一个独立事务。这意味着:
- 语句执行过程中会加行锁(如
SELECT ... FOR UPDATE还是会加锁,但普通 DML 在提交后锁就释放) - 锁的生命周期极短:从语句开始执行 → 获取锁 → 写入/修改 → 写 redo/log → 提交 → 立即释放锁
- 其他会话几乎不会因这条语句被阻塞,除非在毫秒级窗口内恰好并发访问同一行
-
SELECT不加锁(除非显式加FOR UPDATE或LOCK IN SHARE MODE),所以不影响锁资源
autocommit=0 时,锁会一直持有直到 COMMIT 或 ROLLBACK
关闭自动提交后,所有 DML 都进入“累积事务”状态,锁行为发生本质变化:
- 第一行
UPDATE执行时加的行锁,不会在语句结束时释放,而是持续挂起 - 后续同事务内的任何 DML(哪怕操作不同行)都会复用该事务上下文,锁持续累积
- 若事务长时间不
COMMIT,这些锁就一直占用,可能引发:Lock wait timeout exceeded、死锁、或阻塞其他会话的写操作 - 即使只执行一条
UPDATE就断开连接(没COMMIT),InnoDB 会在连接关闭时自动ROLLBACK并释放锁——但这个过程有延迟,期间锁仍有效
DDL 操作不受 autocommit 控制,但会强制触发 COMMIT
CREATE、ALTER、DROP 等 DDL 语句无论 autocommit 是 0 还是 1,都会:
- 隐式开启自己的事务(不可打断)
- 执行完毕后**立即提交**,且无法回滚(
ROLLBACK对它无效) - 在提交前会持有元数据锁(
MDL),阻塞其他对同一表的 DML 或 DDL,持续到其自身事务结束 - 如果当前会话正处在
autocommit = 0的长事务中,DDL 仍会强制中断该事务并提交——这是 MySQL 的硬规则,不是 bug
隔离级别 + autocommit 共同决定“读锁”和“一致性视图”的行为
锁不只是写才涉及;读操作在特定条件下也会间接影响锁等待,尤其在 autocommit = 0 下:
-
SELECT ... FOR UPDATE或SELECT ... LOCK IN SHARE MODE在autocommit = 0时,会把读锁纳入当前事务,直到COMMIT - 即使只是普通
SELECT,在REPEATABLE READ隔离级别下,首次执行时会创建一致性读视图(read view),该视图生命周期绑定当前事务——所以autocommit = 0下,一个空事务(只START TRANSACTION不执行 DML)也能让后续SELECT持有旧快照,间接影响其他会话的可见性判断 -
READ COMMITTED下每次SELECT都新建 read view,所以autocommit对读视图的影响变小,但对写锁依然敏感
autocommit 状态会随连接复用而延续。一个服务端忘了重置 autocommit = 1,下次从连接池拿到这个连接的请求,可能意外进入长事务模式,锁住几秒钟甚至几分钟——而错误日志里往往只报 Lock wait timeout,根本看不出源头是连接复用导致的 autocommit 残留。


















