Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd26df12

Browse files
committed
PBCKP-819: Fixed the recovery-target-timeline command line parameter. It may contain 'current' or 'latest' keywords.
recovery-target can be 'latest' too for compatibility with previous versions
1 parent1ee26f9 commitd26df12

File tree

4 files changed

+147
-11
lines changed

4 files changed

+147
-11
lines changed

‎src/pg_probackup.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static char *target_time = NULL;
9898
staticchar*target_xid=NULL;
9999
staticchar*target_lsn=NULL;
100100
staticchar*target_inclusive=NULL;
101-
staticTimeLineIDtarget_tli;
101+
staticchar*target_tli_string;/* timeline number, "current" or "latest"*/
102102
staticchar*target_stop;
103103
staticbooltarget_immediate;
104104
staticchar*target_name=NULL;
@@ -227,7 +227,7 @@ static ConfigOption cmd_options[] =
227227
{'s',137,"recovery-target-xid",&target_xid,SOURCE_CMD_STRICT },
228228
{'s',144,"recovery-target-lsn",&target_lsn,SOURCE_CMD_STRICT },
229229
{'s',138,"recovery-target-inclusive",&target_inclusive,SOURCE_CMD_STRICT },
230-
{'u',139,"recovery-target-timeline",&target_tli,SOURCE_CMD_STRICT },
230+
{'s',139,"recovery-target-timeline",&target_tli_string,SOURCE_CMD_STRICT },
231231
{'s',157,"recovery-target",&target_stop,SOURCE_CMD_STRICT },
232232
{'f','T',"tablespace-mapping",opt_tablespace_map,SOURCE_CMD_STRICT },
233233
{'f',155,"external-mapping",opt_externaldir_map,SOURCE_CMD_STRICT },
@@ -285,7 +285,7 @@ static ConfigOption cmd_options[] =
285285
{'s',136,"time",&target_time,SOURCE_CMD_STRICT },
286286
{'s',137,"xid",&target_xid,SOURCE_CMD_STRICT },
287287
{'s',138,"inclusive",&target_inclusive,SOURCE_CMD_STRICT },
288-
{'u',139,"timeline",&target_tli,SOURCE_CMD_STRICT },
288+
{'s',139,"timeline",&target_tli_string,SOURCE_CMD_STRICT },
289289
{'s',144,"lsn",&target_lsn,SOURCE_CMD_STRICT },
290290
{'b',140,"immediate",&target_immediate,SOURCE_CMD_STRICT },
291291

@@ -739,7 +739,7 @@ main(int argc, char *argv[])
739739
*/
740740
recovery_target_options=
741741
parseRecoveryTargetOptions(target_time,target_xid,
742-
target_inclusive,target_tli,target_lsn,
742+
target_inclusive,target_tli_string,target_lsn,
743743
(target_stop!=NULL) ?target_stop :
744744
(target_immediate) ?"immediate" :NULL,
745745
target_name,target_action);

‎src/pg_probackup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ typedef struct pgRecoveryTarget
564564
constchar*target_stop;
565565
constchar*target_name;
566566
constchar*target_action;
567+
constchar*target_tli_string;/* timeline number, "current" or "latest" from recovery_target_timeline option*/
567568
}pgRecoveryTarget;
568569

569570
/* Options needed for restore and validate commands */
@@ -893,7 +894,7 @@ extern bool satisfy_recovery_target(const pgBackup *backup,
893894
constpgRecoveryTarget*rt);
894895
externpgRecoveryTarget*parseRecoveryTargetOptions(
895896
constchar*target_time,constchar*target_xid,
896-
constchar*target_inclusive,TimeLineIDtarget_tli,constchar*target_lsn,
897+
constchar*target_inclusive,constchar*target_tli_string,constchar*target_lsn,
897898
constchar*target_stop,constchar*target_name,
898899
constchar*target_action);
899900

‎src/restore.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,8 +1332,10 @@ create_recovery_conf(InstanceState *instanceState, time_t backup_id,
13321332
}
13331333

13341334
/* restore-target='latest' support */
1335-
target_latest=rt->target_stop!=NULL&&
1336-
strcmp(rt->target_stop,"latest")==0;
1335+
target_latest= (rt->target_tli_string!=NULL&&
1336+
strcmp(rt->target_tli_string,"latest")==0)||
1337+
(rt->target_stop!=NULL&&
1338+
strcmp(rt->target_stop,"latest")==0);
13371339

13381340
target_immediate=rt->target_stop!=NULL&&
13391341
strcmp(rt->target_stop,"immediate")==0;
@@ -1359,6 +1361,13 @@ create_recovery_conf(InstanceState *instanceState, time_t backup_id,
13591361
rt->xid_string||rt->lsn_string||rt->target_name||
13601362
target_immediate||target_latest||restore_command_provided)
13611363
params->recovery_settings_mode=PITR_REQUESTED;
1364+
/*
1365+
* The recovery-target-timeline option can be 'latest' for streaming backups.
1366+
* This operation requires a WAL archive for PITR.
1367+
*/
1368+
if (rt->target_tli&&backup->stream&&params->recovery_settings_mode!=PITR_REQUESTED)
1369+
elog(WARNING,"The '--recovery-target-timeline' option applied for STREAM backup. "
1370+
"The timeline number will be ignored.");
13621371

13631372
elog(LOG,"----------------------------------------");
13641373

@@ -1438,14 +1447,20 @@ print_recovery_settings(InstanceState *instanceState, FILE *fp, pgBackup *backup
14381447
fio_fprintf(fp,"recovery_target_timeline = '%u'\n",rt->target_tli);
14391448
else
14401449
{
1450+
if (rt->target_tli_string)
1451+
fio_fprintf(fp,"recovery_target_timeline = '%s'\n",rt->target_tli_string);
1452+
elseif (rt->target_stop&& (strcmp(rt->target_stop,"latest")==0))
1453+
fio_fprintf(fp,"recovery_target_timeline = 'latest'\n");
14411454
#ifPG_VERSION_NUM >=120000
1442-
1455+
else
1456+
{
14431457
/*
14441458
* In PG12 default recovery target timeline was changed to 'latest', which
14451459
* is extremely risky. Explicitly preserve old behavior of recovering to current
14461460
* timneline for PG12.
14471461
*/
14481462
fio_fprintf(fp,"recovery_target_timeline = 'current'\n");
1463+
}
14491464
#endif
14501465
}
14511466

@@ -1877,7 +1892,7 @@ pgRecoveryTarget *
18771892
parseRecoveryTargetOptions(constchar*target_time,
18781893
constchar*target_xid,
18791894
constchar*target_inclusive,
1880-
TimeLineIDtarget_tli,
1895+
constchar*target_tli_string,
18811896
constchar*target_lsn,
18821897
constchar*target_stop,
18831898
constchar*target_name,
@@ -1950,7 +1965,20 @@ parseRecoveryTargetOptions(const char *target_time,
19501965
target_inclusive);
19511966
}
19521967

1953-
rt->target_tli=target_tli;
1968+
rt->target_tli_string=target_tli_string;
1969+
rt->target_tli=0;
1970+
/* target_tli can contains timeline number, "current" or "latest" */
1971+
if(target_tli_string&&strcmp(target_tli_string,"current")!=0&&strcmp(target_tli_string,"latest")!=0)
1972+
{
1973+
errno=0;
1974+
rt->target_tli=strtoul(target_tli_string,NULL,10);
1975+
if (errno==EINVAL||errno==ERANGE|| !rt->target_tli)
1976+
{
1977+
elog(ERROR,"Invalid value for '--recovery-target-timeline' option '%s'",
1978+
target_tli_string);
1979+
}
1980+
}
1981+
19541982
if (target_stop)
19551983
{
19561984
if ((strcmp(target_stop,"immediate")!=0)

‎tests/restore_test.py

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1916,7 +1916,9 @@ def test_restore_target_immediate_archive(self):
19161916
withopen(recovery_conf,'r')asf:
19171917
self.assertIn("recovery_target = 'immediate'",f.read())
19181918

1919-
# @unittest.skip("skip")
1919+
# Skipped, because default recovery_target_timeline is 'current'
1920+
# Before PBCKP-598 the --recovery-target=latest' option did not work and this test allways passed
1921+
@unittest.skip("skip")
19201922
deftest_restore_target_latest_archive(self):
19211923
"""
19221924
make sure that recovery_target 'latest'
@@ -3818,3 +3820,108 @@ def test_restore_with_waldir(self):
38183820
wal_path=os.path.join(node.data_dir,"pg_xlog")
38193821

38203822
self.assertEqual(os.path.islink(wal_path),True)
3823+
3824+
# @unittest.skip("skip")
3825+
deftest_restore_to_latest_timeline(self):
3826+
"""recovery to latest timeline"""
3827+
node=self.make_simple_node(
3828+
base_dir=os.path.join(self.module_name,self.fname,'node'),
3829+
initdb_params=['--data-checksums'])
3830+
3831+
backup_dir=os.path.join(self.tmp_path,self.module_name,self.fname,'backup')
3832+
self.init_pb(backup_dir)
3833+
self.add_instance(backup_dir,'node',node)
3834+
self.set_archiving(backup_dir,'node',node)
3835+
node.slow_start()
3836+
3837+
3838+
node.pgbench_init(scale=2)
3839+
3840+
before1=node.table_checksum("pgbench_branches")
3841+
backup_id=self.backup_node(backup_dir,'node',node)
3842+
3843+
node.stop()
3844+
node.cleanup()
3845+
3846+
self.assertIn(
3847+
"INFO: Restore of backup {0} completed.".format(backup_id),
3848+
self.restore_node(
3849+
backup_dir,'node',node,options=["-j","4"]),
3850+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
3851+
repr(self.output),self.cmd))
3852+
3853+
3854+
3855+
node.slow_start()
3856+
pgbench=node.pgbench(
3857+
stdout=subprocess.PIPE,stderr=subprocess.STDOUT,
3858+
options=['-T','10','-c','2','--no-vacuum'])
3859+
pgbench.wait()
3860+
pgbench.stdout.close()
3861+
3862+
before2=node.table_checksum("pgbench_branches")
3863+
self.backup_node(backup_dir,'node',node)
3864+
3865+
node.stop()
3866+
node.cleanup()
3867+
# restore from first backup
3868+
restore_result=self.restore_node(backup_dir,'node',node,
3869+
options=[
3870+
"-j","4","--recovery-target-timeline=latest","-i",backup_id]
3871+
)
3872+
self.assertIn(
3873+
"INFO: Restore of backup {0} completed.".format(backup_id),restore_result,
3874+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
3875+
repr(self.output),self.cmd))
3876+
3877+
# check recovery_target_timeline option in the recovery_conf
3878+
recovery_target_timeline=self.get_recovery_conf(node)["recovery_target_timeline"]
3879+
self.assertEqual(recovery_target_timeline,"latest")
3880+
# check recovery-target=latest option for compatibility with previous versions
3881+
node.cleanup()
3882+
restore_result=self.restore_node(backup_dir,'node',node,
3883+
options=[
3884+
"-j","4","--recovery-target=latest","-i",backup_id]
3885+
)
3886+
self.assertIn(
3887+
"INFO: Restore of backup {0} completed.".format(backup_id),restore_result,
3888+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
3889+
repr(self.output),self.cmd))
3890+
3891+
# check recovery_target_timeline option in the recovery_conf
3892+
recovery_target_timeline=self.get_recovery_conf(node)["recovery_target_timeline"]
3893+
self.assertEqual(recovery_target_timeline,"latest")
3894+
3895+
# start postgres and promote wal files to latest timeline
3896+
node.slow_start()
3897+
3898+
# check for the latest updates
3899+
after=node.table_checksum("pgbench_branches")
3900+
self.assertEqual(before2,after)
3901+
3902+
# checking recovery_target_timeline=current is the default option
3903+
ifself.pg_config_version>=self.version_to_num('12.0'):
3904+
node.stop()
3905+
node.cleanup()
3906+
3907+
# restore from first backup
3908+
restore_result=self.restore_node(backup_dir,'node',node,
3909+
options=[
3910+
"-j","4","-i",backup_id]
3911+
)
3912+
3913+
self.assertIn(
3914+
"INFO: Restore of backup {0} completed.".format(backup_id),restore_result,
3915+
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
3916+
repr(self.output),self.cmd))
3917+
3918+
# check recovery_target_timeline option in the recovery_conf
3919+
recovery_target_timeline=self.get_recovery_conf(node)["recovery_target_timeline"]
3920+
self.assertEqual(recovery_target_timeline,"current")
3921+
3922+
# start postgres with current timeline
3923+
node.slow_start()
3924+
3925+
# check for the current updates
3926+
after=node.table_checksum("pgbench_branches")
3927+
self.assertEqual(before1,after)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp