diff --git a/src/backend/access/hash/hash_xlog.c b/src/backend/access/hash/hash_xlog.c index 35791b087be..e8ad5804eaf 100644 --- a/src/backend/access/hash/hash_xlog.c +++ b/src/backend/access/hash/hash_xlog.c @@ -17,6 +17,7 @@ #include "access/bufmask.h" #include "access/hash.h" #include "access/hash_xlog.h" +#include "access/xlogrecovery.h" #include "access/xlogutils.h" #include "storage/standby.h" @@ -496,15 +497,15 @@ hash_xlog_move_page_contents(XLogReaderState *record) /* * The cleanup lock on the primary bucket page serializes replay * against scans on a hot standby, which pin the page for their whole - * duration. When hot standby is not active no such scan can exist, - * so we need not read or lock the page. Skipping the read also - * sidesteps a torn copy of the page whose repairing full-page image - * comes later in the WAL: that hazard exists only before consistency - * is reached, which is before hot standby becomes active, so once - * InHotStandby is true any earlier image has already been replayed. - * We do not use the page contents here in any case. + * duration. Scans can run only once hot standby accepts queries, so + * until then we need not read or lock the page. Skipping the read + * also sidesteps a torn copy of the page whose repairing full-page + * image comes later in the WAL: that hazard exists only before + * consistency is reached, and queries are accepted only after that, + * so once HotStandbyActiveInReplay() is true any earlier image has + * already been replayed. */ - if (InHotStandby) + if (HotStandbyActiveInReplay()) (void) XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &bucketbuf); action = XLogReadBufferForRedo(record, 1, &writebuf); @@ -631,15 +632,15 @@ hash_xlog_squeeze_page(XLogReaderState *record) /* * The cleanup lock on the primary bucket page serializes replay * against scans on a hot standby, which pin the page for their whole - * duration. When hot standby is not active no such scan can exist, - * so we need not read or lock the page. Skipping the read also - * sidesteps a torn copy of the page whose repairing full-page image - * comes later in the WAL: that hazard exists only before consistency - * is reached, which is before hot standby becomes active, so once - * InHotStandby is true any earlier image has already been replayed. - * We do not use the page contents here in any case. + * duration. Scans can run only once hot standby accepts queries, so + * until then we need not read or lock the page. Skipping the read + * also sidesteps a torn copy of the page whose repairing full-page + * image comes later in the WAL: that hazard exists only before + * consistency is reached, and queries are accepted only after that, + * so once HotStandbyActiveInReplay() is true any earlier image has + * already been replayed. */ - if (InHotStandby) + if (HotStandbyActiveInReplay()) (void) XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &bucketbuf); if (xldata->ntups > 0 || xldata->is_prev_bucket_same_wrt) @@ -870,15 +871,15 @@ hash_xlog_delete(XLogReaderState *record) /* * The cleanup lock on the primary bucket page serializes replay * against scans on a hot standby, which pin the page for their whole - * duration. When hot standby is not active no such scan can exist, - * so we need not read or lock the page. Skipping the read also - * sidesteps a torn copy of the page whose repairing full-page image - * comes later in the WAL: that hazard exists only before consistency - * is reached, which is before hot standby becomes active, so once - * InHotStandby is true any earlier image has already been replayed. - * We do not use the page contents here in any case. + * duration. Scans can run only once hot standby accepts queries, so + * until then we need not read or lock the page. Skipping the read + * also sidesteps a torn copy of the page whose repairing full-page + * image comes later in the WAL: that hazard exists only before + * consistency is reached, and queries are accepted only after that, + * so once HotStandbyActiveInReplay() is true any earlier image has + * already been replayed. */ - if (InHotStandby) + if (HotStandbyActiveInReplay()) (void) XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &bucketbuf); action = XLogReadBufferForRedo(record, 1, &deletebuf); diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index 52ac6d58423..e091a3e178b 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -390,7 +390,6 @@ static int XLogFileReadAnyTLI(XLogSegNo segno, XLogSource source); static bool CheckForStandbyTrigger(void); static void SetPromoteIsTriggered(void); -static bool HotStandbyActiveInReplay(void); static void SetCurrentChunkStartTime(TimestampTz xtime); static void SetLatestXTime(TimestampTz xtime); @@ -4589,7 +4588,7 @@ HotStandbyActive(void) * Like HotStandbyActive(), but to be used only in WAL replay code, * where we don't need to ask any other process what the state is. */ -static bool +bool HotStandbyActiveInReplay(void) { Assert(AmStartupProcess() || !IsPostmasterEnvironment); diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h index 8786b6d3a8e..11d3eadef3e 100644 --- a/src/include/access/xlogrecovery.h +++ b/src/include/access/xlogrecovery.h @@ -216,6 +216,7 @@ extern void ShutdownWalRecovery(void); extern void RemovePromoteSignalFiles(void); extern bool HotStandbyActive(void); +extern bool HotStandbyActiveInReplay(void); extern XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI); extern RecoveryPauseState GetRecoveryPauseState(void); extern void SetRecoveryPause(bool recoveryPause);