From 4c8ef6795234c1314a33c03eba4cba790e787cca Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Mon, 4 Nov 2024 06:18:08 +0200 Subject: [PATCH v2 1/2] pg_wal_replay_wait(): Improve handling of standby promotion Currently, when pg_wal_replay_wait() finds the server to be not in recovery, it assumes concurrent promotion happened. That leads to certain problems including: 1. No distinction between local recovery as streaming WAL replay, 2. Weird error reporting when there was no recovery. This commit uses PromoteIsTriggered() checks to improve the situation in the following ways: 1. Accept last replay LSN not in recovery mode only when standby was promoted, 2. Show last replay LSN in errdetail() only if standby was promoted. Reported-by: Heikki Linnakangas Discussion: https://postgr.es/m/ab0eddce-06d4-4db2-87ce-46fa2427806c%40iki.fi --- src/backend/access/transam/xlogfuncs.c | 18 ++++++++++++------ src/backend/access/transam/xlogwait.c | 6 ++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index bca1d395683..8abea2dbb57 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -827,12 +827,18 @@ pg_wal_replay_wait(PG_FUNCTION_ARGS) break; case WAIT_LSN_RESULT_NOT_IN_RECOVERY: - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("recovery is not in progress"), - errdetail("Recovery ended before replaying target LSN %X/%X; last replay LSN %X/%X.", - LSN_FORMAT_ARGS(target_lsn), - LSN_FORMAT_ARGS(GetXLogReplayRecPtr(NULL))))); + if (PromoteIsTriggered()) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("recovery is not in progress"), + errdetail("Recovery ended before replaying target LSN %X/%X; last replay LSN %X/%X.", + LSN_FORMAT_ARGS(target_lsn), + LSN_FORMAT_ARGS(GetXLogReplayRecPtr(NULL))))); + else + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("recovery is not in progress"), + errhint("Waiting for LSN can only be executed during recovery."))); break; } diff --git a/src/backend/access/transam/xlogwait.c b/src/backend/access/transam/xlogwait.c index 0ec0898cfbf..fa40762c66a 100644 --- a/src/backend/access/transam/xlogwait.c +++ b/src/backend/access/transam/xlogwait.c @@ -238,7 +238,8 @@ WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout) * the procedure call, while target LSN is replayed. So, we still * check the last replay LSN before reporting an error. */ - if (targetLSN <= GetXLogReplayRecPtr(NULL)) + if (PromoteIsTriggered() && + targetLSN <= GetXLogReplayRecPtr(NULL)) return WAIT_LSN_RESULT_SUCCESS; return WAIT_LSN_RESULT_NOT_IN_RECOVERY; } @@ -276,7 +277,8 @@ WaitForLSNReplay(XLogRecPtr targetLSN, int64 timeout) */ deleteLSNWaiter(); currentLSN = GetXLogReplayRecPtr(NULL); - if (targetLSN <= currentLSN) + if (PromoteIsTriggered() && + targetLSN <= currentLSN) return WAIT_LSN_RESULT_SUCCESS; return WAIT_LSN_RESULT_NOT_IN_RECOVERY; } -- 2.39.5 (Apple Git-154)