MySQL MVCC机制下读写tuple头是否需要加锁?
关于InnoDB MVCC行头读写逻辑的解答
1. 如何理解一致性读“无锁”的表述
我们常说的一致性读无锁,是事务层面的广义无锁,特指一致性读操作不会对用户访问的行加事务级别的S锁/X锁,不会阻塞其他事务对该行的修改操作,和访问行头时用到的细粒度内存锁不是同一维度的概念,二者并不冲突。
2. 行头(tuple Header)的读写实现逻辑
你提到的行头读写互斥问题,InnoDB是靠**Buffer Pool内存页的闩锁(latch)**实现的,和事务层面的锁完全独立:
- 闩锁是保护内存内部结构的轻量级锁,持有时间极短,仅在操作内存页的瞬间持有,操作完成立刻释放,不会跨语句、跨事务存在
- 仅读取行头判断可见性时,只需要持有对应页的共享读闩锁,多个读事务可以同时持有,不会互相阻塞
- 需要修改行头(仅修改最新版本行的trx_id、roll_pointer字段)时,才需要持有对应页的独占写闩锁,持有期间其他对该页的读写操作需要等待
- 闩锁本身支持读写模式,底层默认采用自旋锁实现,拿不到锁时会先自旋固定次数,实在拿不到才会挂起等待,避免不必要的上下文切换
另外需要纠正一个常见误解:更新行生成版本时,旧版本的行头不会被修改,旧版本会直接写入undo日志,仅最新版本的行头会更新roll_pointer指向undo里的旧版本,进一步降低了行头读写的冲突概率。
3. 相关性能开销
闩锁本身的开销极低,且持有时间通常是纳秒级,在常规业务场景下这部分开销完全可以忽略,不会成为性能瓶颈。
内容的提问来源于stack exchange,提问作者Zeng
相关产品推荐
相关产品推荐

