当前位置: 首页 > postgresql, WAL日志 > 正文

第一杀: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 在这里设计了 双引擎并发落盘机制

  1. 主引擎:业务进程(Backend Process)—— 同步提交的死士
    • 当执行 COMMIT; 的那一瞬间(默认 synchronous_commit = on)。
    • 处理这条 SQL 的业务进程(Backend)绝对不会把任务扔给别人。它自己会立刻发起底层的 XLogFlush() 调用,亲手把 WAL Buffer 里属于自己的那段二进制日志死死按进物理硬盘,并在收到操作系统的硬件回执后,才返回给客户端“提交成功”。
  2. 副引擎:walwriter(后台日志清理道夫)—— 异步与兜底
    • 它是一个纯粹的后台清道夫。受参数 wal_writer_delay(默认 200 毫秒)控制,每隔 200 毫秒醒来一次。
    • 它的存在意义:如果 DBA 为了追求极致的 TPS,开启了异步提交(synchronous_commit = off,业务进程 COMMIT 时把数据扔进 WAL Buffer 就直接返回成功了,根本不刷盘。此时,就全靠 walwriter 每 200 毫秒醒来一次,把这些积压在内存里的日志集中剁进硬盘。它在保证极高并发的同时,承担了最多丢失 200 毫秒数据的风险。




了解 www.876873.xyz 的更多信息

订阅后即可通过电子邮件收到最新文章。

组提交魔法(Group Commit,极其核心!):等您坐沙发呢!

发表评论