From 2f552c683cfc3f4ba69a33f279ec80bca60e1c93 Mon Sep 17 00:00:00 2001
From: Atsushi Torikoshi <torikoshia@oss.nttdata.com>
Date: Thu, 27 Mar 2025 10:51:37 +0900
Subject: [PATCH v3] Add hint message when hot standby is unaccessible

Currently, when hot standby is inaccessible due to an overflowed
subtransaction, it is difficult for users to determine the cause
since there are no user level log message indicating that.
This patch adds a hint message to indicate the reasons.

Additionally, there is an inconsistency between the documentation and
the log messages regarding the definition of 'consistent' recovery.
The documentation states that a consistent state requires both recovery
goes beyond minRecoveryPoint and the absence of overflowed
subtransactions, whereas the source code consideres only
minRecoveryPoint.
This patch updates the log message to align with the documentation.

---
 doc/src/sgml/high-availability.sgml       | 1 +
 src/backend/access/transam/xlogrecovery.c | 5 ++++-
 src/backend/tcop/backend_startup.c        | 4 +++-
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index acf3ac0601..6ceb57b0a0 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -1991,6 +1991,7 @@ LOG:  database system is ready to accept read-only connections
        </listitem>
       </itemizedlist>
 
+    The former case can be resolved by closing the transaction.
     If you are running file-based log shipping ("warm standby"), you might need
     to wait until the next WAL file arrives, which could be as long as the
     <varname>archive_timeout</varname> setting on the primary.
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 2c19013c98..8152f90c99 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -2249,7 +2249,7 @@ CheckRecoveryConsistency(void)
 
 		reachedConsistency = true;
 		ereport(LOG,
-				(errmsg("consistent recovery state reached at %X/%X",
+				(errmsg("minimum recovery point reached at %X/%X",
 						LSN_FORMAT_ARGS(lastReplayedEndRecPtr))));
 	}
 
@@ -2268,6 +2268,9 @@ CheckRecoveryConsistency(void)
 		SpinLockRelease(&XLogRecoveryCtl->info_lck);
 
 		LocalHotStandbyActive = true;
+		ereport(LOG,
+				(errmsg("consistent recovery state reached at %X/%X",
+						LSN_FORMAT_ARGS(lastReplayedEndRecPtr))));
 
 		SendPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY);
 	}
diff --git a/src/backend/tcop/backend_startup.c b/src/backend/tcop/backend_startup.c
index 27c0b3c2b0..252443f4ca 100644
--- a/src/backend/tcop/backend_startup.c
+++ b/src/backend/tcop/backend_startup.c
@@ -311,7 +311,9 @@ BackendInitialize(ClientSocket *client_sock, CAC_state cac)
 					ereport(FATAL,
 							(errcode(ERRCODE_CANNOT_CONNECT_NOW),
 							 errmsg("the database system is not yet accepting connections"),
-							 errdetail("Consistent recovery state has not been yet reached.")));
+							 errdetail("Consistent recovery state has not been yet reached."),
+							 errhint("Minimum recovery point has not been yet reached or a write transaction may have more than %d subtransactions.",
+									 PGPROC_MAX_CACHED_SUBXIDS)));
 				else
 					ereport(FATAL,
 							(errcode(ERRCODE_CANNOT_CONNECT_NOW),

base-commit: c325a7633fcb33dbd73f46ddbbe91e95ddf3b227
-- 
2.48.1

