v30-0003-PoC-Ensure-XLogLogicalInfoActive-returns-consist.patch
application/octet-stream
Filename: v30-0003-PoC-Ensure-XLogLogicalInfoActive-returns-consist.patch
Type: application/octet-stream
Part: 0
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: format-patch
Series: patch v30-0003
Subject: PoC: Ensure XLogLogicalInfoActive() returns consistent result.
| File | + | − |
|---|---|---|
| src/backend/access/transam/xact.c | 3 | 0 |
| src/backend/replication/logical/logicalctl.c | 44 | 0 |
| src/include/access/xlog.h | 14 | 7 |
| src/include/replication/logicalctl.h | 2 | 0 |
From b4e067f3ba003cf88e8390406601328443b43a7e Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Tue, 25 Nov 2025 15:59:06 -0800
Subject: [PATCH v30 3/3] PoC: Ensure XLogLogicalInfoActive() returns
consistent result.
---
src/backend/access/transam/xact.c | 3 ++
src/backend/replication/logical/logicalctl.c | 44 ++++++++++++++++++++
src/include/access/xlog.h | 21 ++++++----
src/include/replication/logicalctl.h | 2 +
4 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index d2d3c9b6ed6..02b4328b011 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -2489,6 +2489,7 @@ CommitTransaction(void)
AtEOXact_Snapshot(true, false);
AtEOXact_ApplyLauncher(true);
AtEOXact_LogicalRepWorkers(true);
+ AtEOXact_LogicalCtl();
pgstat_report_xact_timestamp(0);
ResourceOwnerDelete(TopTransactionResourceOwner);
@@ -2784,6 +2785,7 @@ PrepareTransaction(void)
/* we treat PREPARE as ROLLBACK so far as waking workers goes */
AtEOXact_ApplyLauncher(false);
AtEOXact_LogicalRepWorkers(false);
+ AtEOXact_LogicalCtl();
pgstat_report_xact_timestamp(0);
CurrentResourceOwner = NULL;
@@ -3011,6 +3013,7 @@ AbortTransaction(void)
AtEOXact_PgStat(false, is_parallel_worker);
AtEOXact_ApplyLauncher(false);
AtEOXact_LogicalRepWorkers(false);
+ AtEOXact_LogicalCtl();
pgstat_report_xact_timestamp(0);
}
diff --git a/src/backend/replication/logical/logicalctl.c b/src/backend/replication/logical/logicalctl.c
index aee45c790d9..738afae04da 100644
--- a/src/backend/replication/logical/logicalctl.c
+++ b/src/backend/replication/logical/logicalctl.c
@@ -108,6 +108,17 @@ static LogicalDecodingCtlData *LogicalDecodingCtl = NULL;
*/
bool XLogLogicalInfo = false;
+/*
+ * A transaction local cache of XLogLogicalInfo:
+ * -1: not cached yet, need to check XLogLogicalInfo.
+ * 0: cached, XLogLogicalInfo is disabled.
+ * 1: cached, XLogLogicalInfo is enabled.
+ * The cache is set when checking XLogLogicalInfoActive() for the first time
+ * in the transaction and kept until the transaction end. Once the flag value
+ * is cached, this cache is used simply by casting to an boolean.
+ */
+int XLogLogicalInfoXactCache = -1;
+
static void update_xlog_logical_info(void);
static void abort_logical_decoding_activation(int code, Datum arg);
static void write_logical_decoding_status_update_record(bool status);
@@ -213,6 +224,39 @@ IsXLogLogicalInfoEnabled(void)
return xlog_logical_info;
}
+/*
+ * Reset the local cache at end of the transaction.
+ */
+void
+AtEOXact_LogicalCtl(void)
+{
+ XLogLogicalInfoXactCache = -1;
+}
+
+/*
+ * Sub-routine for XLogLogicalInfoActive() to check if logical WAL logging
+ * is enabled. To save function call overheads, the caller must check
+ * the XLogLogicalInfoXactCache first, and use this function only when it's
+ * not set.
+ */
+bool
+CheckXLogLogicalInfoSlow(void)
+{
+ /* Returns the current state if we're out of the transaction */
+ if (!IsTransactionState())
+ return XLogLogicalInfo;
+
+ Assert(XLogLogicalInfoXactCache == -1);
+
+ /*
+ * Cache the current state so as to return the same result within the same
+ * transaction.
+ */
+ XLogLogicalInfoXactCache = (int) XLogLogicalInfo;
+
+ return XLogLogicalInfoXactCache;
+}
+
/*
* Enable or disable both the status of logical info WAL logging and logical
* decoding in shmem.
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 58655d91db7..fded25aba3d 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -13,6 +13,7 @@
#include "access/xlogbackup.h"
#include "access/xlogdefs.h"
+#include "replication/logicalctl.h"
#include "datatype/timestamp.h"
#include "lib/stringinfo.h"
#include "nodes/pg_list.h"
@@ -97,6 +98,7 @@ extern PGDLLIMPORT int wal_level;
extern PGDLLEXPORT int effective_wal_level;
extern PGDLLEXPORT bool XLogLogicalInfo;
+extern PGDLLEXPORT int XLogLogicalInfoXactCache;
/* Is WAL archiving enabled (always or only while server is running normally)? */
#define XLogArchivingActive() \
@@ -128,14 +130,19 @@ extern PGDLLEXPORT bool XLogLogicalInfo;
/*
* Do we need to WAL-log information required only for logical replication?
*
- * When XLogLogicalInfo is true, it enables logical-decoding-related WAL logging
- * as if wal_level were set to 'logical', even if it's actually set to 'replica'.
- * XLogLogicalInfo is a process-local variable, so the value returned by this
- * macro might not reflect the latest state, but is sufficient for process-local
- * WAL-logging decisions. See comments atop logicalctl.c for details on controlling
- * the effective_wal_level.
+ * When XLogLogicalInfoActive() returns true, it enables logical-decoding-related
+ * WAL logging as if wal_level were set to 'logical', even if it's actually set
+ * to 'replica'. The XLogLogicalInfoXactCache is a transaction-local cache so
+ * that this macro ensures to return the same result within the same transaction.
+ * Also, it might not reflect the latest state as it's a process local cache,
+ * but it is sufficient for process-local WAL-logging decisions. See comments
+ * atop logicalctl.c for details on controlling the effective_wal_level.
*/
-#define XLogLogicalInfoActive() (wal_level >= WAL_LEVEL_LOGICAL || XLogLogicalInfo)
+#define XLogLogicalInfoActive() \
+ (wal_level >= WAL_LEVEL_LOGICAL || \
+ (unlikely(XLogLogicalInfoXactCache < 0) ? \
+ CheckXLogLogicalInfoSlow() : \
+ (bool) XLogLogicalInfoXactCache))
#ifdef WAL_DEBUG
extern PGDLLIMPORT bool XLOG_DEBUG;
diff --git a/src/include/replication/logicalctl.h b/src/include/replication/logicalctl.h
index 77ded671473..06423b2ee75 100644
--- a/src/include/replication/logicalctl.h
+++ b/src/include/replication/logicalctl.h
@@ -21,6 +21,8 @@ extern void InitializeProcessXLogLogicalInfo(void);
extern bool ProcessBarrierUpdateXLogLogicalInfo(void);
extern bool IsLogicalDecodingEnabled(void);
extern bool IsXLogLogicalInfoEnabled(void);
+extern bool CheckXLogLogicalInfoSlow(void);
+extern void AtEOXact_LogicalCtl(void);
extern void EnsureLogicalDecodingEnabled(void);
extern void RequestDisableLogicalDecoding(void);
extern void DisableLogicalDecodingIfNecessary(void);
--
2.47.3