第一杀:WAL Buffer 到底有多大?(智能的弹性气闸)
很多人的第一反应是去查文档背一个固定数字。但在现代 PostgreSQL 内核中,这个大小是极其狡猾且自适应的。
- 参数控制:
wal_buffers。 - 默认的物理骗局 (
-1):如果你去查postgresql.conf,你会发现它的默认值是-1。这代表“把控制权彻底交给内核”。 - 底层换算公式:当设置为
-1时,PostgreSQL 启动时会执行一个 C 语言算法:$$WAL\_Buffer\_Size = \min(\frac{Shared\_Buffers}{32}, \text{1 个 WAL 物理段大小 (默认 16MB)})$$- 推演:假设你的服务器内存很大,
shared_buffers设置了 8GB。它的 1/32 是 256MB。但是,内核绝对不允许 WAL Buffer 无限膨胀。它会被生铁焊死的上限(通常是一个 WAL 文件的大小,即 16MB)给强行截断。 - 最小值保底:如果你的系统极度贫穷,算出的大小不能低于 64KB。
- 推演:假设你的服务器内存很大,
- 架构定性:WAL Buffer 是一块极度昂贵、由极其密集的自旋锁(SpinLock)保护的环形共享内存。16MB 对它来说已经足够庞大了,因为里面的数据存活寿命只有几微秒到几十毫秒,就会被狂暴地刷入硬盘。
第二杀:是谁把 WAL Buffer 里的数据砸进硬盘的?(双引擎驱动)
这是一个绝对的面试高频考点。绝大多数人会脱口而出:“是后台的 walwriter(WAL 写入进程)!” 错!在常规的高可用强一致性场景下,真正干脏活的,恰恰是你的业务进程自己!
PostgreSQL 在这里设计了 双引擎并发落盘机制
- 主引擎:业务进程(Backend Process)—— 同步提交的死士
- 当执行
COMMIT;的那一瞬间(默认synchronous_commit = on)。 - 处理这条 SQL 的业务进程(Backend)绝对不会把任务扔给别人。它自己会立刻发起底层的
XLogFlush()调用,亲手把 WAL Buffer 里属于自己的那段二进制日志死死按进物理硬盘,并在收到操作系统的硬件回执后,才返回给客户端“提交成功”。
- 当执行
- 副引擎:
walwriter(后台日志清理道夫)—— 异步与兜底- 它是一个纯粹的后台清道夫。受参数
wal_writer_delay(默认 200 毫秒)控制,每隔 200 毫秒醒来一次。 - 它的存在意义:如果 DBA 为了追求极致的 TPS,开启了异步提交(
synchronous_commit = off),业务进程COMMIT时把数据扔进 WAL Buffer 就直接返回成功了,根本不刷盘。此时,就全靠walwriter每 200 毫秒醒来一次,把这些积压在内存里的日志集中剁进硬盘。它在保证极高并发的同时,承担了最多丢失 200 毫秒数据的风险。
- 它是一个纯粹的后台清道夫。受参数
了解 www.876873.xyz 的更多信息
订阅后即可通过电子邮件收到最新文章。
组提交魔法(Group Commit,极其核心!):等您坐沙发呢!