Re: pg_logical_slot_get_changes waits continously for a partial WAL record spanning across 2 pages
Michael Paquier <michael@paquier.xyz>
From: Michael Paquier <michael@paquier.xyz>
To: vignesh C <vignesh21@gmail.com>
Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>, Alexander Korotkov <aekorotkov@gmail.com>, Tom Lane <tgl@sss.pgh.pa.us>, Amit Kapila <amit.kapila16@gmail.com>, Melanie Plageman <melanieplageman@gmail.com>
Date: 2025-06-26T00:52:20Z
Lists: pgsql-hackers
On Wed, Jun 25, 2025 at 10:19:55PM +0530, vignesh C wrote: > Currently, the logic attempts to read the complete WAL record based on > the size obtained before the crash—even though only a partial record > was written. It then checks the page header to determine whether the > XLP_FIRST_IS_OVERWRITE_CONTRECORD flag is set only after reading the > complete WAL record at XLogDecodeNextRecord function, but since that > much WAL data was not available in the system we never get a chance to > check the header after this.. To address this issue, a more robust > approach would be to first read the page header, check if the > XLP_FIRST_IS_OVERWRITE_CONTRECORD flag is set, and only then proceed > to read the WAL record size if the record is not marked as a partial > overwrite. This would prevent the system from waiting for WAL data > that will never arrive. Attached partial_wal_record_fix.patch patch > for this. So you are suggesting the addition of an extra ReadPageInternal() that forces a read of only the read, perform the checks on the header, then read the rest. After reading SizeOfXLogShortPHD worth of data, shouldn't the checks on xlp_rem_len be done a bit earlier than what you are proposing in this patch? > I don't have a consistent test to reproduce this issue, currently this > issue can be reproduced by running the 046_checkpoint_logical_slot > test about 50 times. This test 046_checkpoint_logical_slot was > reverted recently after it caused a few buildfarm failures discussed > at [2]. The same test is also attached as > reverted_test_046_checkpoint_logical_slot.patch. Seeing the noise that this originally created in the CFbot and the buildfarm, even if the issue would be only triggered after a timeout, I'd vote for relying on this test being good enough for the purpose of this race condition. Another reliable approach would be to make the code wait before reading the record in the internal loop of ReadPageInternal() with an injection point when we know that we have a contrecord, but I'm not really excited about this prospect in xlogreader.c which can be also used in the frontend. -- Michael
Commits
-
Fix infinite wait when reading a partially written WAL record
- c9f4e7520603 17.6 landed
- 762f352ca4a6 13.22 landed
- bedfdb85b0a3 14.19 landed
- 9f270f48f3fe 15.14 landed
- b485e1c89a6d 16.10 landed
- d3917d8f13e7 19 (unreleased) landed
- 5449d5b7ae9c 18.0 landed
-
Improve the stability of the recovery test 047_checkpoint_physical_slot
- fd39c3cf2839 17.6 landed
- c71c702f067b 18.0 landed
- ccd945159361 19 (unreleased) landed
-
Improve recovery test 046_checkpoint_logical_slot
- 6aefde2a2db8 17.6 landed