From c2204691d2ee42965eb9ecbac93c84b4f24879c4 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Sun, 13 Sep 2026 22:53:04 +0000 Subject: [PATCH v10 1/4] Report pages read from WAL buffers in pg_stat_io When any backend (e.g., physical walsender) reads WAL from the WAL buffers, it is not reported anywhere in pg_stat_io. A read from a WAL file is counted in reads and read_bytes. For buffer pool pages, both the reads that find the page in the buffer and the reads that go to disk are counted. This is an observability gap for WAL readers. Fix this by using the existing pg_stat_io.hits column to report the number of pages read from the WAL buffers. This lets users estimate the amount of WAL read from the buffers, by simply multiplying hits with XLOG_BLCKSZ. Author: Bharath Rupireddy Reviewed-by: Michael Paquier Discussion: https://postgr.es/m/CALj2ACVfF2Uj9NoFy-5m98HNtjHpuD17EDE9twVeJng-jTAe7A%40mail.gmail.com --- doc/src/sgml/monitoring.sgml | 6 +++++- src/backend/access/transam/xlog.c | 6 ++++++ src/backend/utils/activity/pgstat_io.c | 9 ++++++--- src/test/recovery/t/001_stream_rep.pl | 9 +++++---- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 6337d2a3d25..276c6447492 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -3316,7 +3316,9 @@ description | Waiting for a newly initialized WAL file to reach durable storage hits bigint - The number of times a desired block was found in a shared buffer. + The number of times a desired block was found in a shared buffer, or + in the WAL buffers for object + wal. @@ -3424,6 +3426,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage writes and write_time track the write activity of WAL files done in XLogWrite. + hits tracks the reads of WAL from the WAL buffers done + in WALReadFromBuffers, which avoid reading a WAL file. See for more information. diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 63d214782da..8636ad9ab2c 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -1850,6 +1850,7 @@ WALReadFromBuffers(char *dstbuf, XLogRecPtr startptr, Size count, XLogRecPtr recptr = startptr; XLogRecPtr inserted; Size nbytes = count; + uint32 npages = 0; if (RecoveryInProgress() || tli != GetWALInsertionTimeLine()) return 0; @@ -1940,10 +1941,15 @@ WALReadFromBuffers(char *dstbuf, XLogRecPtr startptr, Size count, pdst += npagebytes; recptr += npagebytes; nbytes -= npagebytes; + npages++; } Assert(pdst - dstbuf <= count); + /* Report the pages read from the WAL buffers. */ + if (npages > 0) + pgstat_count_io_op(IOOBJECT_WAL, IOCONTEXT_NORMAL, IOOP_HIT, npages, 0); + return pdst - dstbuf; } diff --git a/src/backend/utils/activity/pgstat_io.c b/src/backend/utils/activity/pgstat_io.c index 8ec1aad5078..3c8fcb20aba 100644 --- a/src/backend/utils/activity/pgstat_io.c +++ b/src/backend/utils/activity/pgstat_io.c @@ -525,9 +525,11 @@ pgstat_tracks_io_op(BackendType bktype, IOObject io_object, return false; /* - * Some BackendTypes do not perform reads with IOOBJECT_WAL. + * Some BackendTypes do not perform reads with IOOBJECT_WAL, either from a + * WAL file or from the WAL buffers. */ - if (io_object == IOOBJECT_WAL && io_op == IOOP_READ && + if (io_object == IOOBJECT_WAL && + (io_op == IOOP_READ || io_op == IOOP_HIT) && (bktype == B_WAL_RECEIVER || bktype == B_BG_WRITER || bktype == B_AUTOVAC_LAUNCHER || bktype == B_AUTOVAC_WORKER || bktype == B_DATACHECKSUMSWORKER_LAUNCHER || @@ -567,7 +569,8 @@ pgstat_tracks_io_op(BackendType bktype, IOObject io_object, return false; if (io_object == IOOBJECT_WAL && io_context == IOCONTEXT_NORMAL && - !(io_op == IOOP_WRITE || io_op == IOOP_READ || io_op == IOOP_FSYNC)) + !(io_op == IOOP_WRITE || io_op == IOOP_READ || io_op == IOOP_FSYNC || + io_op == IOOP_HIT)) return false; /* diff --git a/src/test/recovery/t/001_stream_rep.pl b/src/test/recovery/t/001_stream_rep.pl index a4fa4b96c61..f05580a8d6d 100644 --- a/src/test/recovery/t/001_stream_rep.pl +++ b/src/test/recovery/t/001_stream_rep.pl @@ -341,12 +341,13 @@ $node_primary->psql( note "switching to physical replication slot"; -# Wait for the physical WAL sender to update its IO statistics. This is -# done before the next restart, which would force a flush of its stats, and -# far enough from the reset done above to not impact the run time. +# Wait for the physical WAL sender to update its IO statistics (WAL reads from +# buffers and file). This is done before the next restart, which would force a +# flush of its stats, and far enough from the reset done above to not impact +# the run time. $node_primary->poll_query_until( 'postgres', - qq[SELECT sum(reads) > 0 + qq[SELECT sum(reads) + sum(hits) > 0 FROM pg_catalog.pg_stat_io WHERE backend_type = 'walsender' AND object = 'wal'] -- 2.47.3