找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1917

积分

0

好友

254

主题
发表于 2025-12-25 03:48:31 | 查看: 29| 回复: 0

PostgreSQL 15 版本中引入了一对与恢复过程相关的新参数:recovery_prefetchwal_decode_buffer_size。它们旨在通过预读(Prefetch)机制来加速数据库的Redo恢复过程,这对于提升主库故障重启、点播时间恢复以及备库的数据同步效率至关重要。当Redo速度过慢时,会直接影响服务可用性和数据时效性。

预读机制解决的问题

在一个WAL记录中,包含了被修改的数据页信息。在PG15之前,负责恢复的startup进程在处理WAL记录时是串行的:先读取WAL记录,然后再去读取该记录所涉及的数据页,最后应用更改。读取数据页可能命中共享缓冲区,也可能需要从磁盘加载。如果频繁发生磁盘I/O,startup进程将花费大量时间等待,从而拖慢整个恢复流程。

预读工作机制详解

新的预读机制引入了并行化思路。startup进程在读取WAL记录时,流程变得更加复杂与智能:

图片

如图所示,startup进程读取到record1后,会将其放入WAL解码队列,并分析出它涉及两个数据页(pre1pre2)。图中标为红色,意味着这些页不在共享缓冲区中,因此触发了实际的预读操作。

随后,系统会检查WAL队列和预读队列是否已满。若未满,则继续读取下一个record2并放入队列。record2涉及的数据页已在共享缓冲区中(图中标记为绿色),因此只需记录其缓冲区位置,无需触发预读。

这个过程会持续,直到满足以下任一条件则停止预读,并返回record1进行实际的Redo操作:

  1. WAL队列满。
  2. 触发的预读(红色)页数量超过 maintenance_io_concurrency
  3. 涉及的总页数(红色+绿色)超过 4 * maintenance_io_concurrency

实际Redo时的优势:

  • 处理record1时,由于其数据页已被预读,极大概率已缓存在操作系统页面缓存中,startup进程可直接使用,避免了真实的磁盘I/O等待。
  • 处理record2时,会检查之前记录的共享缓冲区位置是否仍有效。若该页未被换出,则直接使用;若被换出,则退回到普通读取流程。

简而言之,该机制的核心思想是将可能阻塞的同步I/O转化为异步的预读任务,让startup进程在系统“后台”加载数据的同时,继续处理其他逻辑,从而大幅减少I/O等待时间,提升数据库/中间件恢复性能。

相关GUC参数解析

  • recovery_prefetch

    • off:关闭预读功能。
    • on:开启预读。如果操作系统不支持预读相关函数,数据库将无法启动。
    • try(默认值):尝试使用预读。若系统支持则启用,否则静默回退到无预读模式。
  • wal_decode_buffer_size

    • 定义了WAL解码队列在内存中可保留的WAL记录总大小的上限(如上图所示)。实际占用可能略微超过此值。
  • maintenance_io_concurrency

    • 这是一个已存在多年的参数,用于定义系统预期的磁盘随机I/O并发能力。
    • 在WAL预读上下文中,它直接限制了一次可以并发发起的预读I/O操作数量

总结与注意事项

预读机制的精髓在于变“被动等待”为“主动调度”,通过异步I/O来掩盖延迟。要有效测试此功能的性能提升,必须确保测试数据集远大于shared_buffers,否则数据全在内存中,预读效果无法显现。

在高负载场景下,备库追同步压力巨大。除了预读,社区也一直在探索并行Redo等更激进的算法/数据结构优化方案,以进一步提升恢复并行度。




上一篇:电机控制器设计解析:实现1500A峰值电流的硬件与散热方案
下一篇:iPhone电池健康保持100%的秘诀:充电设置与日常使用优化
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-11 11:55 , Processed in 0.215685 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表