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