mysql事务回滚会释放锁吗_mysql锁管理与回滚

来源:这里教程网 时间:2026-02-28 20:50:22 作者:

事务回滚时锁是否立即释放?

会,MySQL(InnoDB)在执行

ROLLBACK
的**瞬间**就释放该事务持有的所有锁——包括行锁、间隙锁、临键锁、表级意向锁,甚至临时表锁。这不是“稍后清理”,而是同步清除
lock_sys
中的锁登记项,整个过程原子且不可中断。

为什么不能等“事务结束”再释放?

如果锁等到事务真正退出才释放,就可能造成锁残留或悬挂状态,尤其在连接异常断开、客户端崩溃、或超时 kill 后未显式 rollback 的场景下,锁会卡住其他事务,引发连锁阻塞。InnoDB 的设计原则是:**锁的生命周期严格绑定事务生命周期,事务终止即锁释放**。

显式
ROLLBACK
→ 立即释放全部锁
隐式回滚(如连接中断、语句报错且未捕获)→ MySQL 主动触发回滚并同步释放锁
COMMIT
→ 同样立即释放锁(但此时数据已持久化)

哪些锁“例外”不走这个规则?

绝大多数锁都遵循上述规则,但有一个关键例外:

AUTO-INC
锁。它不是事务锁,而是表级轻量锁,用于保证自增列分配的连续性;它在 INSERT 语句执行完就立刻释放,**与事务是否提交/回滚无关**。这也是为什么高并发插入时,即使事务回滚了,自增值也不会回退。

另外注意:某些显式加的表锁(如

LOCK TABLES ... WRITE
)不属于事务锁体系,它们不受
ROLLBACK
影响,必须用
UNLOCK TABLES
手动释放——这类锁已基本被 InnoDB 行锁取代,日常开发中应避免使用。

实操中容易踩的坑

开发者常误以为“只要没 COMMIT,锁就一直占着”,从而在应用层做长事务或手动 sleep 等待,结果导致锁堆积、死锁频发。真实情况是:

事务空闲等待期间,锁照常持有,其他事务会被阻塞(尤其是写锁) 哪怕只执行了一条
SELECT ... FOR UPDATE
就停住,锁也一直不放,直到 rollback 或 commit
Spring 声明式事务中,若 service 方法抛出未被捕获的运行时异常,框架会自动 rollback → 锁也会随之释放;但如果 catch 了异常又没 re-throw,事务可能意外提交或挂起,锁行为变得不可控

最稳妥的做法:事务粒度尽量短,读写分离清晰,避免在事务中调用外部服务或执行耗时操作——锁不是资源池里的可复用对象,它是排他性的“占用凭证”,越早交出,系统越顺畅。

相关推荐