第一道闸门:私有内存 -> wal_buffers(抢夺 WALInsertLock)
【物理动作】:
业务进程在自己的私有内存(Local Memory)里,已经把 XLogRecord(核弹头)组装好了。现在,它要把这串二进制数据**拷贝(Copy)**到全局共享的 wal_buffers 环形队列里。
【争夺的锁】:WALInsertLock(WAL 插入锁)
【原厂面试绝杀考点(PG 9.4 以后的极限优化)】:
如果你在面试时说“所有进程都在抢同一把插入锁”,考官会直接把你淘汰。因为那是十几年前的老黄历了!
- 远古时代的悲剧:以前确实只有一把独占锁。10 万个并发进程为了把数据拷进内存,全卡在这一把锁上,CPU 疯狂上下文切换,TPS 根本上不去。
- 现在的多兵团线列阵(Partitioned Locks):为了压榨多核 CPU 的极限,原厂架构师把
WALInsertLock劈成了一个数组(默认包含 8 把轻量级锁 LWLock)! - 微秒级推演:
- 进程先通过极其廉价的 CPU 原子操作(Atomic Fetch-and-Add),在
wal_buffers里“圈地”(预留出自己需要的字节空间,比如 100 字节)。 - 圈好地后,它从 8 把
WALInsertLock中随机抢一把。 - 抢到锁后,它把私有内存里的数据,精准地拷贝到刚才圈好的 100 字节空间里。
- 拷贝完成,瞬间释放插入锁。
- 进程先通过极其廉价的 CPU 原子操作(Atomic Fetch-and-Add),在
- 定性:这叫**“空间分配原子化,数据拷贝并发化”。它允许最多 8 个进程同时**向
wal_buffers的不同位置写入数据!
第二道闸门:wal_buffers -> 物理硬盘(抢夺 WALWriteLock)
【物理动作】:
数据已经安全躺在 wal_buffers 里了。现在,业务进程(或者 walwriter)要发起系统调用 write() 和 fsync(),把这段内存数据砸进底层磁盘。
【争夺的锁】:WALWriteLock(WAL 写锁)
【冷酷的物理法则】:
- 绝对的独裁(排他锁):与插入锁的“多兵团并发”完全不同,向磁盘发起 I/O 请求,是一项极其沉重且必须严格保序的物理动作。因此,
WALWriteLock全局只有唯一的一把,且是绝对的排他锁(Exclusive Lock)! - 微秒级推演(衔接我们刚才的组提交魔法):
- 100 个已经完成插入(释放了
WALInsertLock)的进程,同时扑向这把唯一的WALWriteLock。 - 抢到这把锁的那个唯一进程,瞬间加冕为**“带头大哥”**。
- 没抢到锁的 99 个小弟,立刻进入操作系统的休眠队列(Sleep Queue),交出 CPU 控制权。
- “带头大哥”捏着这把
WALWriteLock,代表所有人,执行极其沉重的fsync磁盘锤击。 - 硬盘回执返回,落盘完成。大哥释放
WALWriteLock,并唤醒所有小弟。
- 100 个已经完成插入(释放了
- 定性:它是整个组提交(Group Commit)魔法的物理阵眼。没有这把全局唯一的排他锁来“堵住”大军,就不可能把成百上千的并发碎 I/O 揉成一次巨大的顺序写!
了解 www.876873.xyz 的更多信息
订阅后即可通过电子邮件收到最新文章。
每个 进程 在自己的私有内存里面生产的 wal日志写入到 wal buffer里面的时候,会抢什么锁?? wdal日志由wal buffer 落盘的时候会抢夺什么锁??:等您坐沙发呢!