mysql事务回滚时锁会释放吗_mysql锁释放机制解析

1次阅读

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

mysql事务回滚时锁会释放吗_mysql锁释放机制解析

事务回滚时锁一定会释放吗?

会,但不是“立刻”或“无条件”释放——ROLLBACK 执行完成的那一刻,该事务持有的所有行锁、表锁(含意向锁)都会被清除。这是 InnoDB 的硬性保证:事务生命周期结束,锁生命周期同步终结。但要注意,**锁的释放发生在回滚操作“执行完毕后”,而非“回滚语句发出时”**。如果回滚本身因大事务、大量 undo 日志回放而卡住(比如几十万行更新后回滚),那锁就持续阻塞着其他事务,直到回滚真正完成。

哪些锁在回滚前就可能被提前释放?

绝大多数锁都严格等到事务结束(COMMITROLLBACK 完成)才释放;但有两类例外:

  • 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_TRXINNODB_LOCK_WAITS,而不是凭感觉判断锁是否释放。

显式锁(LOCK tableS)和事务锁行为完全不同

这是最容易混淆的点:用 LOCK TABLES tb_name WRITE 加的锁,**不受事务控制**。它不会因为 ROLLBACKCOMMIT 自动释放,必须显式执行 UNLOCK TABLES。一旦忘记解锁,整个连接会一直持锁,甚至阻塞 DDL 操作(如 ALTER TABLE)。

  • MyISAM 表只能靠这种显式表锁,没有事务概念
  • InnoDB 表上混用 LOCK TABLES 和事务极危险:事务内加的行锁 + 显式表锁叠加,容易引发不可预测的阻塞链
  • 现代应用应避免 LOCK TABLES,改用行级事务锁 + 合理隔离级别

真正需要关注锁释放时机的,永远是 InnoDB 行锁与事务边界的对齐问题——而不是把表锁、意向锁、MDL 锁全混在一起谈“释放”。

text=ZqhQzanResources