Hi, On Sat, Sep 12, 2026 at 4:52 AM Paul Kim <[email protected]> wrote: > > Whether XactLastRecEnd > receiving a "start of the next record" position deserves a fix of its > own is a fair follow-up question; the other consumers appear to cope > with it, so I kept it out of this patch series.
Thanks for sending the v4 patches. TBH, fixing it in the WAL writer looks like fixing the symptom of the issue. That approach also seems to have a problem. XLogCtl->asyncXactLSN doesn't change until new WAL is written, so the WAL writer keeps using the old value (B+40) and keeps logging "request to flush past end of generated WAL" messages. How about adjusting EndPos itself to the start of the segment (before the page header) using XLogBytePosToEndRecPtr in this case, where the switch WAL record falls right on the segment boundary, something like the attached? This way, the switch record's EndPos (B+40) no longer goes into XactLastRecEnd and XLogCtl->asyncXactLSN, and from there into the WAL writer and WaitXLogInsertionsToFinish(). It fixes the issue for me and the regression tests pass. -- Bharath Rupireddy Amazon Web Services: https://aws.amazon.com
From 3fe41b9281855e37458385a7172f984f9f974924 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy <[email protected]> Date: Fri, 9 Oct 2026 04:16:25 +0000 Subject: [PATCH] Fix end LSN reported for an xlog-switch record ending on a page boundary A page header size is added to the end of an xlog-switch record even when the record ends exactly on a page boundary and crosses no header. At a segment boundary that puts the end past the end of reserved WAL. The position then goes into the asynchronous commit LSN, and from there into the WAL writer, which keeps logging "request to flush past end of generated WAL" and reports write and flush positions for WAL that was never written. Adjust the end position to the start of the segment (before the page header) using XLogBytePosToEndRecPtr(), the way it is done for any other record. The bad position then no longer goes into the asynchronous commit LSN or the WAL writer. More blah. --- src/backend/access/transam/xlog.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index afbe068cd0a..72ec58551ed 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -1077,21 +1077,14 @@ XLogInsertRecord(XLogRecData *rdata, /* * Even though we reserved the rest of the segment for us, which is * reflected in EndPos, we return a pointer to just the end of the - * xlog-switch record. + * xlog-switch record. When the record falls right on the segment + * boundary, EndPos is adjusted to the start of the segment (before + * the page header), so that it doesn't go past the end of reserved + * WAL. */ if (inserted) - { - EndPos = StartPos + SizeOfXLogRecord; - if (StartPos / XLOG_BLCKSZ != EndPos / XLOG_BLCKSZ) - { - uint64 offset = XLogSegmentOffset(EndPos, wal_segment_size); - - if (offset == EndPos % XLOG_BLCKSZ) - EndPos += SizeOfXLogLongPHD; - else - EndPos += SizeOfXLogShortPHD; - } - } + EndPos = XLogBytePosToEndRecPtr(XLogRecPtrToBytePos(StartPos) + + MAXALIGN(SizeOfXLogRecord)); } /* Process any flush progress published while making room for the record. */ -- 2.47.3
