会,MySQL事务执行ROLLBACK时立即释放所有锁,包括行锁、表锁、间隙锁等;InnoDB同步清理lock_sys中登记的全部锁对象,释放彻底且瞬时。

会。MySQL 事务执行 ROLLBACK 时,**立即释放该事务持有的所有锁**(包括行锁、表锁、间隙锁等),这是 InnoDB 的强制行为,无需额外操作。
事务回滚时锁是否真被清除了?
是的,且非常彻底。InnoDB 在 ROLLBACK 过程中不仅撤销所有未提交的修改,还会同步清理事务在 lock_sys 中登记的所有锁对象。你可以通过 SHOW ENGINE INNODB STATUS\G 观察到 TRANSACTIONS 部分的锁信息随事务消失而清空。
- 回滚后,其他被阻塞的事务(如等待
SELECT ... FOR UPDATE的连接)会立刻被唤醒并继续执行 - 即使回滚发生在超时前(比如手动触发),锁也**不会残留**——和
COMMIT一样干净 - 注意:回滚本身可能耗时较长(尤其大事务),这段时间锁仍被持有;但一旦回滚完成,释放是瞬时的
为什么有时候回滚后还有锁没释放?
那通常不是“回滚没释放”,而是你没真正执行回滚,或者锁根本不在当前事务里。常见误判场景:
-
autocommit = 1模式下,单条UPDATE执行完就自动提交了,后续ROLLBACK对它无效——它压根没在事务里 - 用
LOCK TABLES ... WRITE加的是显式表锁,这类锁**不参与事务生命周期**,必须配对使用UNLOCK TABLES - 死锁被检测后,InnoDB 自动回滚的是“牺牲者”事务,但你的客户端可能没收到错误(比如网络中断),误以为还在运行
- 长事务未提交,又没设
innodb_lock_wait_timeout,别人在等你,你以为自己“已回滚”,其实你根本没发ROLLBACK
怎么验证锁确实释放了?
别靠猜,用两个终端实测最可靠:
-- 终端 A:开启事务并加锁 START TRANSACTION; SELECT * FROM accounts WHERE id = 1 FOR UPDATE;-- 终端 B:尝试更新同一行(会卡住) UPDATE accounts SET balance = 100 WHERE id = 1;
-- 终端 A:执行回滚 ROLLBACK;
-- 终端 B:立刻返回成功(不再卡住)
如果终端 B 仍卡住,说明终端 A 的事务没真正结束(可能连接断了但事务还挂着,或用了 MyISAM 引擎——它不支持行锁和事务)。
真正要注意的,从来不是“回滚会不会释放锁”,而是“你发起的到底是不是一个受事务管理的锁”。InnoDB 的锁释放逻辑极其确定,出问题的地方,90% 在事务边界没理清、引擎选错、或混淆了显式锁与隐式锁。










