You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudberry.apache.org by ma...@apache.org on 2024/12/23 11:11:02 UTC

(cloudberry) 07/23: Check recoveryTargetAction before put PM_STATUS_STANDBY

This is an automated email from the ASF dual-hosted git repository.

maxyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 4f08c7fdac7d3922e7c630940090ec015c75c933
Author: Kate Dontsova <kd...@vmware.com>
AuthorDate: Wed May 11 17:03:26 2022 -0700

    Check recoveryTargetAction before put PM_STATUS_STANDBY
    
       Earlier https://github.com/greenplum-db/gpdb-postgres-merge/commit/67a589c6ec2467256a33075d0be9fad1b46a1514
       introduced checking for promote_trigger_file before
       put PM_STATUS_STANDBY into postmaster.pid as if we intend
       to promote - PM_STATUS_READY will be written when promotion
       completes. However promote_trigger_file is not the only option
       to request promotion. In case of recovery setting recovery_target_action
       configuration parameter to 'promote' will also result
       into promotion after recovery is completed.
    
       Scenario to reproduce:
       - enable wal_archiving
       - take pg_basebackup
       - insert some data and call gp_create_restore_point() + gp_switch_log()
       - restore the cluster from backup, specify recovery_target_name to
         your restore point, recovery_target_action = promote and hot_standby=off
       - start the cluster
       - gpstart will fail with [CRITICAL]:-gpstart failed.
         (Reason='FATAL:  the database system is starting up...)
         because the underlying pg_ctl start will return early
         and the following attempt to connect fails.
---
 src/backend/postmaster/postmaster.c                | 19 +++++--
 .../recovery/t/103_promotion_wait_status_ready.pl  | 59 ++++++++++++++++++++++
 2 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index eadb8a4224..e70e91b33f 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -5786,7 +5786,7 @@ sigusr1_handler(SIGNAL_ARGS)
 		pmState == PM_STARTUP && Shutdown == NoShutdown)
 	{
 		/* WAL redo has started. We're out of reinitialization. */
-		bool		promote_trigger_file_exist;
+		bool		promotion_requested = false;
 
 		FatalError = false;
 		AbortStartTime = 0;
@@ -5813,21 +5813,32 @@ sigusr1_handler(SIGNAL_ARGS)
 		 * PM_STATUS_STANDBY, instead wish pg_ctl -w to wait till
 		 * connections can be actually accepted by the database.
 		 */
-		promote_trigger_file_exist = false;
 		if (PromoteTriggerFile != NULL && strcmp(PromoteTriggerFile, "") != 0)
 		{
 			struct stat stat_buf;
 
 			if (stat(PromoteTriggerFile, &stat_buf) == 0)
-				promote_trigger_file_exist = true;
+				promotion_requested = true;
 		}
+		/*
+		 * GPDB: Setting recovery_target_action
+		 * configuration parameter to 'promote' will also result
+		 * into promotion after recovery is completed.
+		 */
+		if (recoveryTargetAction == RECOVERY_TARGET_ACTION_PROMOTE)
+			promotion_requested = true;
 
 		/*
 		 * If we aren't planning to enter hot standby mode later, treat
 		 * RECOVERY_STARTED as meaning we're out of startup, and report status
 		 * accordingly.
+		 *
+		 * GPDB: Avoid PM_STATUS_STANDBY if promotion requested as wish "pg_ctl -w"
+		 * to wait till connections can be actually accepted by the database via
+		 * PM_STATUS_READY state instead. PM_STATUS_STANDBY will incorrectly show
+		 * database is ready to accept connections during promotion.
 		 */
-		if (!EnableHotStandby && !promote_trigger_file_exist)
+		if (!EnableHotStandby && !promotion_requested)
 		{
 			AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STANDBY);
 #ifdef USE_SYSTEMD
diff --git a/src/test/recovery/t/103_promotion_wait_status_ready.pl b/src/test/recovery/t/103_promotion_wait_status_ready.pl
new file mode 100644
index 0000000000..db573377f9
--- /dev/null
+++ b/src/test/recovery/t/103_promotion_wait_status_ready.pl
@@ -0,0 +1,59 @@
+# Checks that if promotion is requested in recovery_target_action
+# we are waiting for recovery to complete before let pg_ctl to return
+use strict;
+use warnings;
+
+use PostgresNode;
+use TestLib;
+use Test::More tests => 1;
+
+# Initialize node to backup
+my $node_to_backup = get_new_node('to_backup');
+$node_to_backup->init(
+	has_archiving    => 1,
+	allows_streaming => 1);
+$node_to_backup->start;
+
+# And some content
+$node_to_backup->safe_psql('postgres',
+	"CREATE TABLE tab_1 AS SELECT generate_series(1, 10) AS a1");
+$node_to_backup->safe_psql('postgres',
+	"SELECT pg_create_restore_point('first_restore_point');");
+$node_to_backup->safe_psql('postgres',
+	"SELECT pg_switch_wal();");
+
+# Take backup
+my $backup_name = 'my_backup';
+$node_to_backup->backup($backup_name);
+
+# Before running the transaction get the
+# current timestamp that will be used as a comparison base.
+my $trx_to_archive_time = time();
+# Add some more content, create restore point and switch WAL to make sure it's archived
+$node_to_backup->safe_psql('postgres',
+	"CREATE TABLE tab_2 AS SELECT generate_series(1, 10) AS a2");
+$node_to_backup->safe_psql('postgres',
+	"SELECT pg_create_restore_point('second_restore_point');");
+$node_to_backup->safe_psql('postgres',
+	"SELECT pg_switch_wal();");
+
+# Create new node from from backup
+my $node_restored = get_new_node('restored');
+my $delay         = 5;
+$node_restored->init_from_backup($node_to_backup, $backup_name,
+	standby => 1, has_restoring => 1);
+$node_restored->append_conf(
+	'postgresql.conf', qq(
+recovery_target_name = 'second_restore_point'
+recovery_target_action = 'promote'
+recovery_min_apply_delay = '${delay}s'
+hot_standby = 'off'
+));
+$node_restored->start;
+
+#Promotion can happen only after the recovery process spends
+# recovery_min_apply_delay seconds en route to the recovery_target_name.
+#Thus, this check ensures that pg_ctl waited for promotion to have completed before returning.
+
+ok(time() - $trx_to_archive_time >= $delay,
+	"pg_ctl starts restored node only after replication delay if recovery_target_action = 'promote' is specified");


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cloudberry.apache.org
For additional commands, e-mail: commits-help@cloudberry.apache.org