public inbox for [email protected]  
help / color / mirror / Atom feed
From: 贾明伟 <[email protected]>
To: Heikki Linnakangas <[email protected]>
Cc: John Naylor <[email protected]>
Cc: pgsql-hackers <[email protected]>
Cc: Andres Freund <[email protected]>
Cc: Andrey M. Borodin <[email protected]>
Cc: Kirill Reshke <[email protected]>
Subject: Re: CSN snapshots in hot standby
Date: Sun, 13 Apr 2025 21:17:36 +0800
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
	<CALdSSPgbnsq_ZOLd59tORg0-onQ0RVrMP_gQ_HudfJS14ecytQ@mail.gmail.com>
	<[email protected]>
	<[email protected]>
	<swzptfywx4i2jj65oi3v3atsiywho3qzr5rj4rjr7ktzpxinmh@nwoaps6qvuqy>
	<[email protected]>
	<[email protected]>
	<CANWCAZaxwGfZxD1KQb88_eLUPj_yx7Sc3B1y6-kjVN2g7wy1iw@mail.gmail.com>
	<[email protected]>
	<[email protected]>
	<[email protected]>

Hi all,

Apologies — the patch I sent earlier did not appear as expected on the mailing list archives because of wrong attachment style. 

I'll resend it properly as an inline patch shortly.

Thanks for your understanding!

Best regards,  
Mingwei Jia



Attachments:

  [application/octet-stream] v7-0013-use-clog-in-XidInMVCCSnapshot.patch (5.3K, ../[email protected]/2-v7-0013-use-clog-in-XidInMVCCSnapshot.patch)
  download | inline diff:
From 5cbb8e5806a444df04ed2f54d1c45f4aa1ea8f7b Mon Sep 17 00:00:00 2001
From: Mingwei Jia <[email protected]>
Date: Sat, 12 Apr 2025 21:10:44 +0800
Subject: [PATCH] If the checkpoint's oldestActiveXid at standby startup is
 less than nextXid, then the visibility of transactions within that range
 should be determined using the CLOG. This is because there may be
 transactions in that range that have already committed on the primary, and
 these committed transactions will not be replayed again on the standby.

---
 src/backend/access/transam/xlog.c             |  2 ++
 src/backend/storage/ipc/procarray.c           |  4 +++
 src/backend/utils/time/snapmgr.c              | 12 ++++++++
 src/include/access/transam.h                  |  2 ++
 src/include/storage/procarray.h               |  2 ++
 .../modules/test_misc/t/008_csnstandby.pl     | 30 +++++++++++++++++++
 6 files changed, 52 insertions(+)
 create mode 100644 src/test/modules/test_misc/t/008_csnstandby.pl

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index deb2cd1883c..2796458491d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5565,6 +5565,8 @@ StartupXLOG(void)
 	TransamVariables->nextXid = checkPoint.nextXid;
 	TransamVariables->nextOid = checkPoint.nextOid;
 	TransamVariables->oidCount = 0;
+	TransamVariables->nextXidStandbyStart =
+					XidFromFullTransactionId(checkPoint.nextXid);
 	MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
 	AdvanceOldestClogXid(checkPoint.oldestXid);
 	SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index c82e8d8c438..d4c67512c56 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -962,6 +962,10 @@ ProcArrayUpdateOldestRunningXid(TransactionId oldestRunningXID)
 	procArray->oldest_running_primary_xid = oldestRunningXID;
 	LWLockRelease(ProcArrayLock);
 }
+TransactionId GetOldestRunningXid(void)
+{
+	return 	procArray->oldest_running_primary_xid;
+}
 
 
 /*
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index df9e8ba37f4..0ebcb0af835 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -1969,6 +1969,18 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
 		uint32		cache_idx = snapshot->xmax - xid;
 		uint64		wordno = cache_idx / INPROGRESS_CACHE_XIDS_PER_WORD;
 		uint64		slotno = (cache_idx % INPROGRESS_CACHE_XIDS_PER_WORD) * INPROGRESS_CACHE_BITS;
+		TransactionId nextXidStart = TransamVariables->nextXidStandbyStart;
+		TransactionId oldestRunning = GetOldestRunningXid();
+
+		if (TransactionIdPrecedes(oldestRunning, nextXidStart)
+			&& TransactionIdPrecedes(xid, nextXidStart))
+		{
+			if (TransactionIdDidCommit(xid) || TransactionIdDidAbort(xid))
+			{
+				return false;
+			}
+			return true;
+		}
 
 		if (snapshot->inprogress_cache)
 		{
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index a7054fe11cd..a75d66f4d40 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -240,6 +240,8 @@ typedef struct TransamVariablesData
 
 	/* During recovery, LSN of latest replayed commit record */
 	XLogRecPtr	latestCommitLSN;
+	/* checkpoint`s next xid when hot-standby start */
+	TransactionId nextXidStandbyStart;
 
 	/*
 	 * Number of top-level transactions with xids (i.e. which may have
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index de74fce24e4..a4129de8101 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -29,6 +29,8 @@ extern void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid);
 extern void ProcArrayClearTransaction(PGPROC *proc);
 
 extern void ProcArrayUpdateOldestRunningXid(TransactionId oldestRunningXID);
+
+extern TransactionId GetOldestRunningXid(void);
 extern void ProcArrayInitRecovery(TransactionId initializedUptoXID);
 
 extern void RecordKnownAssignedTransactionIds(TransactionId xid);
diff --git a/src/test/modules/test_misc/t/008_csnstandby.pl b/src/test/modules/test_misc/t/008_csnstandby.pl
new file mode 100644
index 00000000000..98708490d91
--- /dev/null
+++ b/src/test/modules/test_misc/t/008_csnstandby.pl
@@ -0,0 +1,30 @@
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $primary = PostgreSQL::Test::Cluster->new('primary');
+$primary->init();
+$primary->append_conf('postgresql.conf', 'max_wal_senders = 5');
+$primary->append_conf('postgresql.conf', 'wal_level=replica');
+$primary->start;
+my $count = '';
+$primary->safe_psql('postgres', 'create table t1(i int, j int)');
+
+my $primary_a =  $primary->background_psql('postgres', on_error_die => 1);
+$primary_a->query_safe("begin");
+$primary_a->query_safe("insert into t1 values(1,1)");
+$primary->safe_psql('postgres', 'insert into t1 values(2,1)');
+$primary->backup('bkp');
+
+my $replica = PostgreSQL::Test::Cluster->new('replica');
+$replica->init_from_backup($primary, 'bkp', has_streaming => 1);
+$replica->start;
+
+$count = $replica->safe_psql('postgres', "select count(*) from t1");
+is($count, '1', "get right visiablity before primary checkpoint in hot standby");
+
+done_testing();
+
--
2.45.0



view thread (18+ messages)

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: CSN snapshots in hot standby
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox