PostgreSQL码农集散地

PostgreSQL 18 preview - 增强wal receiver进程的WAL写入监控

PostgreSQL 18 preview - 增强wal receiver进程的WAL写入监控

此 patch 的主要目标是增强对 PostgreSQL 中 WAL(Write-Ahead Logging)接收器写入操作的监控能力。WAL 接收器负责从主节点接收 WAL 数据并将其写入备节点的磁盘中。为了更好地分析和优化 WAL 写入性能。

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=7f7f324eb5a4754ab9fa1c68dfef952555a94d1b

Add more monitoring data for WAL writes in the WAL receiver  
author Michael Paquier <[email protected]>   
Thu, 6 Mar 2025 00:39:45 +0000 (09:39 +0900)  
committer Michael Paquier <[email protected]>   
Thu, 6 Mar 2025 00:41:37 +0000 (09:41 +0900)  
commit 7f7f324eb5a4754ab9fa1c68dfef952555a94d1b  
tree 42188169b43b62372ea8e91c3f735fd3cd40d283 tree  
parent 393e0d2314050576c9c039853fdabe7f685a4f47 commit | diff  
Add more monitoring data for WAL writes in the WAL receiver  

This commit adds two improvements related to the monitoring of WAL  
writes for the WAL receiver.  

First, write counts and timings are now counted in pg_stat_io for the  
WAL receiver.  These have been discarded from pg_stat_wal in
ff99918c625a due to performance concerns, related to the fact that we  
still relied on an on-disk file for the stats back then, even with  
track_wal_io_timing to avoid the overhead of the timestamp calculations.  
This implementation is simpler than the original proposal as it is  
possible to rely on the APIs of pgstat_io.c to do the job.  Like the  
fsync and read data, track_wal_io_timing needs to be enabled to track  
the timings.  

Second, a wait event is added around the pg_pwrite() call in charge of  
the writes, using the exiting WAIT_EVENT_WAL_WRITE.  This is useful as  
the WAL receiver data is tracked in pg_stat_activity.  

Reviewed-by: Bertrand Drouvot <[email protected]>  
Discussion: https://postgr.es/m/[email protected]  

Patch 的主要内容

  1. 将 WAL 写入统计信息添加到 pg_stat_io

  • 原因:
    在之前的提交(ff99918c625a)中,由于性能问题,WAL 写入的统计信息被从 pg_stat_wal 中移除了。当时的主要瓶颈是统计信息依赖于磁盘文件,即使启用了 track_wal_io_timing 来避免时间戳计算的开销,仍然存在性能问题。
  • 改进:
    现在通过 pgstat_io.c 提供的 API 实现了更简单的解决方案,将 WAL 写入的计数和时间统计添加到 pg_stat_io 中。
  • 启用条件:
    需要启用 track_wal_io_timing 参数来跟踪时间统计信息。
  • 意义:
    这使得用户可以通过 pg_stat_io 查看 WAL 接收器的写入性能,包括写入次数和耗时等详细信息。
  • 为 pg_pwrite() 调用添加等待事件

    • 改动内容:
      在 WAL 接收器的 pg_pwrite() 调用周围添加了一个等待事件,使用现有的 WAIT_EVENT_WAL_WRITE。
    • 意义:
      通过此改动,WAL 接收器的写入操作可以被记录到 pg_stat_activity 中。这有助于用户分析 WAL 写入过程中可能的阻塞或延迟问题。

    代码改动细节

    diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c  
    index 83129cb92afe3f43fc9ebf9a0325b394a2f91e7e..2e5dd6deb2c2e4b4c8d4ff78d7250375ee78e5d6 100644 (file)  
    --- a/src/backend/replication/walreceiver.c  
    +++ b/src/backend/replication/walreceiver.c  
    @@ -922,6 +922,7 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr, TimeLineID tli)  
     {  
        int         startoff;  
        int         byteswritten;  
    +   instr_time  start;  

        Assert(tli != 0);  

    @@ -952,7 +953,18 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr, TimeLineID tli)  
            /* OK to write the logs */  
            errno = 0;  

    +       /*  
    +        * Measure I/O timing to write WAL data, for pg_stat_io.  
    +        */  
    +       start = pgstat_prepare_io_time(track_wal_io_timing);  
    +  
    +       pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE);  
            byteswritten = pg_pwrite(recvFile, buf, segbytes, (off_t) startoff);  
    +       pgstat_report_wait_end();  
    +  
    +       pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL,  
    +                               IOOP_WRITE, start, 1, byteswritten);  
    +  
    if (byteswritten <= 0)  
            {  
                char        xlogfname[MAXFNAMELEN];  

    新增 I/O 时间测量

    • 位置:XLogWalRcvWrite 函数
    • 改动点:
      +       start = pgstat_prepare_io_time(track_wal_io_timing);  
      • 引入了 instr_time 类型变量 start,用于记录 WAL 写入操作的时间起点。
      • 使用 pgstat_prepare_io_time 函数初始化时间测量,仅当 track_wal_io_timing 启用时才生效。

    添加等待事件

    • 位置:XLogWalRcvWrite 函数
    • 改动点:
      +       pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE);  
      • 在调用 pg_pwrite() 写入 WAL 数据之前,报告开始等待事件 WAIT_EVENT_WAL_WRITE。
      • 写入完成后结束等待事件:
        +       pgstat_report_wait_end();  

    记录 I/O 操作统计

    • 位置:XLogWalRcvWrite 函数
    • 改动点:
      +       pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL,  
      +                               IOOP_WRITE, start, 1, byteswritten);  
      • IOOBJECT_WAL:表示操作对象为 WAL 文件。
      • IOCONTEXT_NORMAL:表示上下文为普通操作。
      • IOOP_WRITE:表示操作类型为写入。
      • start:记录的时间起点。
      • 1:表示单次操作。
      • byteswritten:实际写入的字节数。
      • 使用 pgstat_count_io_op_time 函数记录 WAL 写入的 I/O 操作统计信息。
      • 参数说明:

    关键功能与实现

    1. I/O 时间测量

    • 通过 pgstat_prepare_io_time 和 pgstat_count_io_op_time,精确测量 WAL 写入操作的耗时。
    • 这些数据会被记录到 pg_stat_io 表中,便于用户分析 WAL 写入性能。
  • 等待事件跟踪

    • 添加了 WAIT_EVENT_WAL_WRITE 等待事件,用于标识 WAL 写入操作。
    • 这些事件会被记录到 pg_stat_activity 表中,方便用户监控 WAL 接收器的状态。

    启用条件与配置

    • track_wal_io_timing 参数:
      • 必须启用该参数才能跟踪 WAL 写入的时间统计信息。
      • 默认值为 off,需要手动设置为 on 才能启用。