v2-0002-nbtree-Use-cleanup-locks-in-redo-for-IOS-interloc.patch

application/octet-stream

Filename: v2-0002-nbtree-Use-cleanup-locks-in-redo-for-IOS-interloc.patch
Type: application/octet-stream
Part: 1
Message: Re: TID recycling race during nbtree index-only scans that run on a standby

Patch

Format: format-patch
Series: patch v2-0002
Subject: nbtree: Use cleanup locks in redo for IOS interlock
File+
src/backend/access/nbtree/nbtxlog.c 9 2
From 88d911bc032a04bc5e935353fdd0a35fcb981a34 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Mon, 22 Jun 2026 13:34:11 +0200
Subject: [PATCH v2 2/2] nbtree: Use cleanup locks in redo for IOS interlock

We need to interlock tuple clean with IOS' page pins on the primary,
and this is no different on a hot standby replica.  This naturally
requires btree_xlog_delete to use a Cleanup lock on the buffer it's
removing tuples from.

Additionally, because page splits can remove tuples from a page that
IOS still holds a pin on, and those removed tuples can then be
deleted from the index without an interlock with the split page,
btree_xlog_split must also use a cleanup lock for page splits.

Reported-by: Peter Geoghegan <pg@bowt.ie>
---
 src/backend/access/nbtree/nbtxlog.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c
index dff7d286fc8..8940db7de34 100644
--- a/src/backend/access/nbtree/nbtxlog.c
+++ b/src/backend/access/nbtree/nbtxlog.c
@@ -300,7 +300,13 @@ btree_xlog_split(bool newitemonleft, XLogReaderState *record)
 	MarkBufferDirty(rbuf);
 
 	/* Now reconstruct original page (left half of split) */
-	if (XLogReadBufferForRedo(record, 0, &buf) == BLK_NEEDS_REDO)
+	/*
+	 * Note: We're moving tuples off the page that a concurrent IOS won't
+	 * get a cleanup interlock with if they're DELETE-d, so we must do that
+	 * interlock here and now to avoid IOScans losing a vacuum interlock.
+	 */
+	if (XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true,
+									  &buf) == BLK_NEEDS_REDO)
 	{
 		/*
 		 * To retain the same physical order of the tuples that they had, we
@@ -664,7 +670,8 @@ btree_xlog_delete(XLogReaderState *record)
 	 * We don't need to take a cleanup lock to apply these changes. See
 	 * nbtree/README for details.
 	 */
-	if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
+	if (XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true,
+									  &buffer) == BLK_NEEDS_REDO)
 	{
 		char	   *ptr = XLogRecGetBlockData(record, 0, NULL);
 
-- 
2.50.1 (Apple Git-155)