Skip to content

Commit

Permalink
Remove standby.signal if the data is backuped from standby (#158)
Browse files Browse the repository at this point in the history
* Remove standby.signal if the data is backuped from standby

Although pg_rman doesn't treat the backup as restoring on
standby automatically, it remains standby.signal. So, this
patch removes the file.

* update for review comments
  • Loading branch information
mikecaat committed Apr 30, 2021
1 parent 95281f7 commit dbf9458
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 15 deletions.
23 changes: 23 additions & 0 deletions expected/backup_from_standby.out
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,26 @@
0
0
0

###### BACKUP COMMAND FROM STANDBY SERVER TEST-0003 ######
0
0
0

###### must be primary even if the recovery target is latest ######
pg_is_in_recovery
-------------------
f
(1 row)

###### BACKUP COMMAND FROM STANDBY SERVER TEST-0004 ######
0
0
0

###### must be standby and synchronized with the primary server ######
status
-----------
streaming
(1 row)

39 changes: 39 additions & 0 deletions restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static void add_recovery_related_options(const char *target_time,
TimeLineID target_tli,
bool target_tli_latest);
static void create_recovery_signal(void);
static void remove_standby_signal(void);

static pgRecoveryTarget *checkIfCreateRecoveryConf(const char *target_time,
const char *target_xid,
Expand Down Expand Up @@ -378,6 +379,12 @@ do_restore(const char *target_time,
/* Create recovery.signal file */
create_recovery_signal();

/*
* Remove if standby.signal file exists because pg_rman doesn’t treat
* the backup as restoring on standby automatically now.
*/
remove_standby_signal();

/* release catalog lock */
catalog_unlock();

Expand Down Expand Up @@ -799,6 +806,38 @@ create_recovery_signal(void)
}
}

static void
remove_standby_signal(void)
{
struct stat stat_buf;
char path[MAXPGPATH];

if (verbose && !check)
printf(_("----------------------------------------\n"));

elog(INFO, _("removing standby.signal if exists to restore as primary"));

if (!check)
{
snprintf(path, lengthof(path), "%s/standby.signal", pgdata);

if (stat(path, &stat_buf) == 0)
{
if (remove(path))
{
ereport(ERROR,
(errcode(ERROR_SYSTEM),
errmsg("could not remove \"%s\": %s", path,
strerror(errno))));
}
ereport(INFO,
(errmsg("removed standby.signal"),
errhint("if you want to start as standby, additional manual"
"setups to make standby.signal and so on are required")));
}
}
}

static void
backup_online_files(bool re_recovery)
{
Expand Down
96 changes: 81 additions & 15 deletions sql/backup_from_standby.sh
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,43 @@ EOF
pg_ctl -D ${SBYDATA_PATH} start -w -t 600 > /dev/null 2>&1
}

function load_with_pgbench
{
pgbench -p ${TEST_PGPORT} -T ${DURATION} -d pgbench > /dev/null 2>&1
}

function full_backup_from_standby
{
pg_rman backup -B ${BACKUP_PATH} -b full -Z -p ${TEST_PGPORT} -d postgres -D ${SBYDATA_PATH} --standby-host=localhost --standby-port=${TEST_SBYPGPORT} --quiet;echo $?
pg_rman validate -B ${BACKUP_PATH} --quiet; echo $?
}

function incremental_backup_from_standby
{
pg_rman backup -B ${BACKUP_PATH} -b incremental -Z -p ${TEST_PGPORT} -d postgres -D ${SBYDATA_PATH} --standby-host=localhost --standby-port=${TEST_SBYPGPORT} --quiet;echo $?
pg_rman validate -B ${BACKUP_PATH} --quiet; echo $?
}

function get_database_data_from_primary
{
psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -c "SELECT * FROM pgbench_branches;"
}

function get_database_data_from_standby
{
psql -p ${TEST_SBYPGPORT} --no-psqlrc -d pgbench -c "SELECT * FROM pgbench_branches;"
}

init_backup
setup_standby
init_catalog
echo '###### BACKUP COMMAND FROM STANDBY SERVER TEST-0001 ######'
echo '###### full backup mode ######'
pgbench -p ${TEST_PGPORT} -T ${DURATION} -d pgbench > /dev/null 2>&1
psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -c "SELECT * FROM pgbench_branches;" > ${TEST_BASE}/TEST-0001-before.out
pg_rman backup -B ${BACKUP_PATH} -b full -Z -p ${TEST_PGPORT} -d postgres -D ${SBYDATA_PATH} --standby-host=localhost --standby-port=${TEST_SBYPGPORT} --quiet;echo $?
pg_rman validate -B ${BACKUP_PATH} --quiet; echo $?
load_with_pgbench
get_database_data_from_primary > ${TEST_BASE}/TEST-0001-before.out
full_backup_from_standby
TARGET_XID=`psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -tAq -c "INSERT INTO pgbench_history VALUES (1) RETURNING(xmin);"`
pgbench -p ${TEST_PGPORT} -T ${DURATION} -d pgbench > /dev/null 2>&1
load_with_pgbench
pg_ctl stop -m immediate -D ${PGDATA_PATH} > /dev/null 2>&1
cp ${PGDATA_PATH}/postgresql.conf ${TEST_BASE}/postgresql.conf
sleep 1
Expand All @@ -173,7 +199,7 @@ ${BACKUP_RESTORE_COMMAND}
${BACKUP_TARGET_XID_COMMAND}
EOF
pg_ctl start -w -t 600 -D ${PGDATA_PATH} > /dev/null 2>&1
psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -c "SELECT * FROM pgbench_branches;" > ${TEST_BASE}/TEST-0001-after.out
get_database_data_from_primary > ${TEST_BASE}/TEST-0001-after.out
diff ${TEST_BASE}/TEST-0001-before.out ${TEST_BASE}/TEST-0001-after.out
echo ''

Expand All @@ -182,15 +208,13 @@ setup_standby
init_catalog
echo '###### BACKUP COMMAND FROM STANDBY SERVER TEST-0002 ######'
echo '###### full + incremental backup mode ######'
pgbench -p ${TEST_PGPORT} -d pgbench > /dev/null 2>&1
pg_rman backup -B ${BACKUP_PATH} -b full -Z -p ${TEST_PGPORT} -d postgres -D ${SBYDATA_PATH} --standby-host=localhost --standby-port=${TEST_SBYPGPORT} --quiet;echo $?
pg_rman validate -B ${BACKUP_PATH} --quiet; echo $?
pgbench -p ${TEST_PGPORT} -T ${DURATION} -d pgbench > /dev/null 2>&1
pg_rman backup -B ${BACKUP_PATH} -b incremental -Z -p ${TEST_PGPORT} -d postgres -D ${SBYDATA_PATH} --standby-host=localhost --standby-port=${TEST_SBYPGPORT} --quiet;echo $?
pg_rman validate -B ${BACKUP_PATH} --quiet; echo $?
psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -c "SELECT * FROM pgbench_branches;" > ${TEST_BASE}/TEST-0002-before.out
load_with_pgbench
full_backup_from_standby
load_with_pgbench
incremental_backup_from_standby
get_database_data_from_primary > ${TEST_BASE}/TEST-0002-before.out
TARGET_XID=`psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -tAq -c "INSERT INTO pgbench_history VALUES (1) RETURNING(xmin);"`
pgbench -p ${TEST_PGPORT} -T ${DURATION} pgbench > /dev/null 2>&1
load_with_pgbench
pg_ctl stop -m immediate -D ${PGDATA_PATH} > /dev/null 2>&1
cp ${PGDATA_PATH}/postgresql.conf ${TEST_BASE}/postgresql.conf
sleep 1
Expand All @@ -203,9 +227,51 @@ ${BACKUP_RESTORE_COMMAND}
${BACKUP_TARGET_XID_COMMAND}
EOF
pg_ctl start -w -t 600 -D ${PGDATA_PATH} > /dev/null 2>&1
psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -c "SELECT * FROM pgbench_branches;" > ${TEST_BASE}/TEST-0002-after.out
get_database_data_from_primary > ${TEST_BASE}/TEST-0002-after.out
diff ${TEST_BASE}/TEST-0002-before.out ${TEST_BASE}/TEST-0002-after.out
echo ''

# check to start as primary (stand-alone) if the recovery target is latest
init_backup
setup_standby
init_catalog
echo '###### BACKUP COMMAND FROM STANDBY SERVER TEST-0003 ######'
load_with_pgbench
get_database_data_from_primary > ${TEST_BASE}/TEST-0003-before.out
full_backup_from_standby
# Don't load_with_pgbench again. It makes the *.out result difference because
# restoring to the latest point using archived wal including the one generated
# by the second load.
pg_ctl stop -m immediate -D ${PGDATA_PATH} > /dev/null 2>&1
pg_rman restore -B ${BACKUP_PATH} -D ${PGDATA_PATH} --quiet;echo $?
sed -i -e "s/^port = .*$/port = ${TEST_PGPORT}/" ${PGDATA_PATH}/postgresql.conf
pg_ctl start -w -t 600 -D ${PGDATA_PATH} > /dev/null 2>&1
get_database_data_from_primary > ${TEST_BASE}/TEST-0003-after.out
diff ${TEST_BASE}/TEST-0003-before.out ${TEST_BASE}/TEST-0003-after.out
echo ''
echo '###### must be primary even if the recovery target is latest ######'
sleep 3 # wait until finishing recovery
psql -p ${TEST_PGPORT} --no-psqlrc -d pgbench -c "SELECT pg_is_in_recovery();"

# check to start as standby if a user configure it manually
init_backup
setup_standby
init_catalog
echo '###### BACKUP COMMAND FROM STANDBY SERVER TEST-0004 ######'
load_with_pgbench
full_backup_from_standby
load_with_pgbench # this data will be replicated after restoring
get_database_data_from_primary > ${TEST_BASE}/TEST-0004-before.out
pg_ctl stop -m immediate -D ${SBYDATA_PATH} > /dev/null 2>&1
pg_rman restore -B ${BACKUP_PATH} -D ${SBYDATA_PATH} --quiet;echo $?
touch ${SBYDATA_PATH}/standby.signal # configure for standby server
pg_ctl start -w -t 600 -D ${SBYDATA_PATH} > /dev/null 2>&1
echo ''
echo '###### must be standby and synchronized with the primary server ######'
sleep 3 # wait until finishing to sync
psql -p ${TEST_SBYPGPORT} --no-psqlrc -d pgbench -c "SELECT status FROM pg_stat_wal_receiver;"
get_database_data_from_standby > ${TEST_BASE}/TEST-0004-after.out
diff ${TEST_BASE}/TEST-0004-before.out ${TEST_BASE}/TEST-0004-after.out

# clean up the temporal test data
pg_ctl stop -m immediate -D ${PGDATA_PATH} > /dev/null 2>&1
Expand Down

0 comments on commit dbf9458

Please sign in to comment.