是,但非立刻释放——rollback执行完毕时,事务持有的所有行锁、表锁(含意向锁)才被清除;大事务回滚卡住会导致锁持续阻塞,直至回滚完成。

事务回滚时锁一定会释放吗?
会,但不是“立刻”或“无条件”释放——ROLLBACK 执行完成的那一刻,该事务持有的所有行锁、表锁(含意向锁)都会被清除。这是 InnoDB 的硬性保证:事务生命周期结束,锁生命周期同步终结。但要注意,**锁的释放发生在回滚操作“执行完毕后”,而非“回滚语句发出时”**。如果回滚本身因大事务、大量 undo 日志回放而卡住(比如几十万行更新后回滚),那锁就持续阻塞着其他事务,直到回滚真正完成。
哪些锁在回滚前就可能被提前释放?
绝大多数锁都严格等到事务结束(COMMIT 或 ROLLBACK 完成)才释放;但有两类例外:
-
READ-COMMITTED隔离级别下,select语句扫描但不匹配WHERE条件的行,其临时加的行锁会在扫描完该行后立即释放,哪怕事务还没结束——这不是为回滚服务,而是为减少锁持有时间 - 某些只读查询中用到的“权宜之计”类锁(如内部优化器临时加的元数据锁),也会在语句执行完即丢弃,和事务终点无关
注意:这些都不是用户可控的释放行为,也不适用于 UPDATE/delete 等写操作——它们的锁铁定扛到事务终点。
为什么有时回滚完了,别的事务还在等锁?
常见错觉。真实情况通常是以下之一:
- 你的
ROLLBACK命令已发,但 mysql 还没执行完(可通过SHOW ENGINE INNODB STATUS查看TRANSACTIONS部分,确认状态是否为ROLLING BACK) - 另一个事务在你回滚前就已获取了锁(比如它先执行了
UPDATE并未提交),你回滚解决不了它的锁 - 死锁检测触发了自动回滚(
Deadlock found when trying to get lock),但被回滚的是对方事务,你的事务可能仍在等待——别误以为“自己回滚了,锁就没了”
排查时优先看 INFORMATION_SCHEMA.INNODB_TRX 和 INNODB_LOCK_WAITS,而不是凭感觉判断锁是否释放。
显式锁(LOCK tableS)和事务锁行为完全不同
这是最容易混淆的点:用 LOCK TABLES tb_name WRITE 加的锁,**不受事务控制**。它不会因为 ROLLBACK 或 COMMIT 自动释放,必须显式执行 UNLOCK TABLES。一旦忘记解锁,整个连接会一直持锁,甚至阻塞 DDL 操作(如 ALTER TABLE)。
- MyISAM 表只能靠这种显式表锁,没有事务概念
- InnoDB 表上混用
LOCK TABLES和事务极危险:事务内加的行锁 + 显式表锁叠加,容易引发不可预测的阻塞链 - 现代应用应避免
LOCK TABLES,改用行级事务锁 + 合理隔离级别
真正需要关注锁释放时机的,永远是 InnoDB 行锁与事务边界的对齐问题——而不是把表锁、意向锁、MDL 锁全混在一起谈“释放”。