会。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; <p>-- 终端 B:尝试更新同一行(会卡住) UPDATE accounts SET balance = 100 WHERE id = 1;</p><p>-- 终端 A:执行回滚 ROLLBACK;</p><p>-- 终端 B:立刻返回成功(不再卡住)
如果终端 B 仍卡住,说明终端 A 的事务没真正结束(可能连接断了但事务还挂着,或用了 MyISAM 引擎——它不支持行锁和事务)。
真正要注意的,从来不是“回滚会不会释放锁”,而是“你发起的到底是不是一个受事务管理的锁”。InnoDB 的锁释放逻辑极其确定,出问题的地方,90% 在事务边界没理清、引擎选错、或混淆了显式锁与隐式锁。
