wait_replication_slot_xmin.patch

application/octet-stream

Filename: wait_replication_slot_xmin.patch
Type: application/octet-stream
Part: 0
Message: 回复: BUG #18213: Standby's repeatable read isolation level transaction encountered a "nonrepeatable read" problem

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/commands/indexcmds.c 19 0
src/backend/storage/ipc/procarray.c 12 0
src/include/storage/procarray.h 1 0
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 0b3b8e98b8..cf3e1d449c 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -424,6 +424,8 @@ WaitForOlderSnapshots(TransactionId limitXmin, bool progress)
 	int			n_old_snapshots;
 	int			i;
 	VirtualTransactionId *old_snapshots;
+	TransactionId replication_slot_xmin = InvalidTransactionId;
+	TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
 
 	old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
 										  PROC_IS_AUTOVACUUM | PROC_IN_VACUUM
@@ -483,6 +485,23 @@ WaitForOlderSnapshots(TransactionId limitXmin, bool progress)
 		if (progress)
 			pgstat_progress_update_param(PROGRESS_WAITFOR_DONE, i + 1);
 	}
+
+	do
+	{
+		/*
+		 * Wait for the oldest replication slot xmin to exceed limitXmin to prevent
+		 * standby being unable to access old version data through the newly built
+		 * index.
+		 * It is necessary to wait only if replication_slot_xmin is "normal".
+		 */
+		CHECK_FOR_INTERRUPTS();
+		GetReplicationSlotXmin(&replication_slot_xmin, &replication_slot_catalog_xmin);
+		if (!TransactionIdIsNormal(replication_slot_xmin))
+			break;
+		if (!NormalTransactionIdPrecedes(replication_slot_xmin, limitXmin))
+			break;
+		pg_usleep(1000000);
+	} while (true);
 }
 
 
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 80ab026bf5..e314b54fe3 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -2503,6 +2503,18 @@ GetSnapshotData(Snapshot snapshot)
 	return snapshot;
 }
 
+/*
+ * Get replication_slot_xmin and replication_slot_catalog_xmin from ProcArrayStruct
+ */
+void
+GetReplicationSlotXmin(TransactionId* xmin, TransactionId* catalog_xmin)
+{
+	LWLockAcquire(ProcArrayLock, LW_SHARED);
+	*xmin = procArray->replication_slot_xmin;
+	*catalog_xmin = procArray->replication_slot_catalog_xmin;
+	LWLockRelease(ProcArrayLock);
+}
+
 /*
  * ProcArrayInstallImportedXmin -- install imported xmin into MyProc->xmin
  *
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index d8cae3ce1c..f985aae96d 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -45,6 +45,7 @@ extern int	GetMaxSnapshotXidCount(void);
 extern int	GetMaxSnapshotSubxidCount(void);
 
 extern Snapshot GetSnapshotData(Snapshot snapshot);
+extern void GetReplicationSlotXmin(TransactionId* xmin, TransactionId* catalog_xmin);
 
 extern bool ProcArrayInstallImportedXmin(TransactionId xmin,
 										 VirtualTransactionId *sourcevxid);