]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix correctness issue with computation of FPI size in WAL stats
authorMichael Paquier <michael@paquier.xyz>
Wed, 29 Oct 2025 00:13:31 +0000 (09:13 +0900)
committerMichael Paquier <michael@paquier.xyz>
Wed, 29 Oct 2025 00:13:31 +0000 (09:13 +0900)
XLogRecordAssemble() may be called multiple times before inserting a
record in XLogInsertRecord(), and the amount of FPIs generated inside
a record whose insertion is attempted multiple times may vary.

The logic added in f9a09aa29520 touched directly pgWalUsage in
XLogRecordAssemble(), meaning that it could be possible for pgWalUsage
to be incremented multiple times for a single record.  This commit
changes the code to use the same logic as the number of FPIs added to a
record, where XLogRecordAssemble() returns this information and feeds it
to XLogInsertRecord(), updating pgWalUsage only when a record is
inserted.

Reported-by: Shinya Kato <shinya11.kato@gmail.com>
Discussion: https://postgr.es/m/CAOzEurSiSr+rusd0GzVy8Bt30QwLTK=ugVMnF6=5WhsSrukvvw@mail.gmail.com

src/backend/access/transam/xlog.c
src/backend/access/transam/xloginsert.c
src/include/access/xlog.h

index eceab3412558bcac6cfd0a343ee336c25d38971e..fd91bcd68ecd3017960222b6a8e2e408e52ea37f 100644 (file)
@@ -749,6 +749,7 @@ XLogInsertRecord(XLogRecData *rdata,
                                 XLogRecPtr fpw_lsn,
                                 uint8 flags,
                                 int num_fpi,
+                                uint64 fpi_bytes,
                                 bool topxid_included)
 {
        XLogCtlInsert *Insert = &XLogCtl->Insert;
@@ -1081,6 +1082,7 @@ XLogInsertRecord(XLogRecData *rdata,
                pgWalUsage.wal_bytes += rechdr->xl_tot_len;
                pgWalUsage.wal_records++;
                pgWalUsage.wal_fpi += num_fpi;
+               pgWalUsage.wal_fpi_bytes += fpi_bytes;
 
                /* Required for the flush of pending stats WAL data */
                pgstat_report_fixed = true;
index b3abf386f801c2f5ec6b53e14894342792543611..58cb4b1b00c9957d1bb547262e216da49ef67906 100644 (file)
@@ -139,6 +139,7 @@ static MemoryContext xloginsert_cxt;
 static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info,
                                                                           XLogRecPtr RedoRecPtr, bool doPageWrites,
                                                                           XLogRecPtr *fpw_lsn, int *num_fpi,
+                                                                          uint64 *fpi_bytes,
                                                                           bool *topxid_included);
 static bool XLogCompressBackupBlock(const PageData *page, uint16 hole_offset,
                                                                        uint16 hole_length, void *dest, uint16 *dlen);
@@ -512,6 +513,7 @@ XLogInsert(RmgrId rmid, uint8 info)
                XLogRecPtr      fpw_lsn;
                XLogRecData *rdt;
                int                     num_fpi = 0;
+               uint64          fpi_bytes = 0;
 
                /*
                 * Get values needed to decide whether to do full-page writes. Since
@@ -521,10 +523,11 @@ XLogInsert(RmgrId rmid, uint8 info)
                GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);
 
                rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
-                                                                &fpw_lsn, &num_fpi, &topxid_included);
+                                                                &fpw_lsn, &num_fpi, &fpi_bytes,
+                                                                &topxid_included);
 
                EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
-                                                                 topxid_included);
+                                                                 fpi_bytes, topxid_included);
        } while (EndPos == InvalidXLogRecPtr);
 
        XLogResetInsertion();
@@ -562,7 +565,8 @@ XLogSimpleInsertInt64(RmgrId rmid, uint8 info, int64 value)
 static XLogRecData *
 XLogRecordAssemble(RmgrId rmid, uint8 info,
                                   XLogRecPtr RedoRecPtr, bool doPageWrites,
-                                  XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
+                                  XLogRecPtr *fpw_lsn, int *num_fpi, uint64 *fpi_bytes,
+                                  bool *topxid_included)
 {
        XLogRecData *rdt;
        uint64          total_len = 0;
@@ -800,8 +804,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info,
                        total_len += bimg.length;
 
                        /* Track the WAL full page images in bytes */
-                       pgWalUsage.wal_fpi_bytes += bimg.length;
-                       pgstat_report_fixed = true;
+                       *fpi_bytes += bimg.length;
                }
 
                if (needs_data)
index d12798be3d8078ce772512fc9f62bb85ca4b5458..a12757e46e5ba8e4d68cb0d4336f336d494aa114 100644 (file)
@@ -202,6 +202,7 @@ extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
                                                                   XLogRecPtr fpw_lsn,
                                                                   uint8 flags,
                                                                   int num_fpi,
+                                                                  uint64 fpi_bytes,
                                                                   bool topxid_included);
 extern void XLogFlush(XLogRecPtr record);
 extern bool XLogBackgroundFlush(void);