1 # Test for recovery targets: name, timestamp, XID
6 use Test::More tests => 9;
8 # Create and test a standby from given backup, with a certain recovery target.
9 # Choose $until_lsn later than the transaction commit that causes the row
10 # count to reach $num_rows, yet not later than the recovery target.
11 sub test_recovery_standby
13 my $test_name = shift;
14 my $node_name = shift;
15 my $node_master = shift;
16 my $recovery_params = shift;
18 my $until_lsn = shift;
20 my $node_standby = get_new_node($node_name);
21 $node_standby->init_from_backup($node_master, 'my_backup',
24 foreach my $param_item (@$recovery_params)
26 $node_standby->append_conf('recovery.conf', qq($param_item));
31 # Wait until standby has replayed enough data
33 "SELECT '$until_lsn'::pg_lsn <= pg_last_wal_replay_lsn()";
34 $node_standby->poll_query_until('postgres', $caughtup_query)
35 or die "Timed out while waiting for standby to catch up";
37 # Create some content on master and check its presence in standby
39 $node_standby->safe_psql('postgres', "SELECT count(*) FROM tab_int");
40 is($result, qq($num_rows), "check standby content for $test_name");
43 $node_standby->teardown_node;
46 # Initialize master node
47 my $node_master = get_new_node('master');
48 $node_master->init(has_archiving => 1, allows_streaming => 1);
53 # Create data before taking the backup, aimed at testing
54 # recovery_target = 'immediate'
55 $node_master->safe_psql('postgres',
56 "CREATE TABLE tab_int AS SELECT generate_series(1,1000) AS a");
58 $node_master->safe_psql('postgres', "SELECT pg_current_wal_lsn();");
60 # Take backup from which all operations will be run
61 $node_master->backup('my_backup');
63 # Insert some data with used as a replay reference, with a recovery
65 $node_master->safe_psql('postgres',
66 "INSERT INTO tab_int VALUES (generate_series(1001,2000))");
67 my $ret = $node_master->safe_psql('postgres',
68 "SELECT pg_current_wal_lsn(), txid_current();");
69 my ($lsn2, $recovery_txid) = split /\|/, $ret;
71 # More data, with recovery target timestamp
72 $node_master->safe_psql('postgres',
73 "INSERT INTO tab_int VALUES (generate_series(2001,3000))");
75 $node_master->safe_psql('postgres', "SELECT pg_current_wal_lsn();");
76 my $recovery_time = $node_master->safe_psql('postgres', "SELECT now()");
78 # Even more data, this time with a recovery target name
79 $node_master->safe_psql('postgres',
80 "INSERT INTO tab_int VALUES (generate_series(3001,4000))");
81 my $recovery_name = "my_target";
83 $node_master->safe_psql('postgres', "SELECT pg_current_wal_lsn();");
84 $node_master->safe_psql('postgres',
85 "SELECT pg_create_restore_point('$recovery_name');");
87 # And now for a recovery target LSN
88 $node_master->safe_psql('postgres',
89 "INSERT INTO tab_int VALUES (generate_series(4001,5000))");
90 my $lsn5 = my $recovery_lsn =
91 $node_master->safe_psql('postgres', "SELECT pg_current_wal_lsn()");
93 $node_master->safe_psql('postgres',
94 "INSERT INTO tab_int VALUES (generate_series(5001,6000))");
96 # Force archiving of WAL file
97 $node_master->safe_psql('postgres', "SELECT pg_switch_wal()");
99 # Test recovery targets
100 my @recovery_params = ("recovery_target = 'immediate'");
101 test_recovery_standby('immediate target',
102 'standby_1', $node_master, \@recovery_params, "1000", $lsn1);
103 @recovery_params = ("recovery_target_xid = '$recovery_txid'");
104 test_recovery_standby('XID', 'standby_2', $node_master, \@recovery_params,
106 @recovery_params = ("recovery_target_time = '$recovery_time'");
107 test_recovery_standby('time', 'standby_3', $node_master, \@recovery_params,
109 @recovery_params = ("recovery_target_name = '$recovery_name'");
110 test_recovery_standby('name', 'standby_4', $node_master, \@recovery_params,
112 @recovery_params = ("recovery_target_lsn = '$recovery_lsn'");
113 test_recovery_standby('LSN', 'standby_5', $node_master, \@recovery_params,
117 # Last entry has priority (note that an array respects the order of items
120 "recovery_target_name = '$recovery_name'",
121 "recovery_target_xid = '$recovery_txid'",
122 "recovery_target_time = '$recovery_time'");
123 test_recovery_standby('name + XID + time',
124 'standby_6', $node_master, \@recovery_params, "3000", $lsn3);
126 "recovery_target_time = '$recovery_time'",
127 "recovery_target_name = '$recovery_name'",
128 "recovery_target_xid = '$recovery_txid'");
129 test_recovery_standby('time + name + XID',
130 'standby_7', $node_master, \@recovery_params, "2000", $lsn2);
132 "recovery_target_xid = '$recovery_txid'",
133 "recovery_target_time = '$recovery_time'",
134 "recovery_target_name = '$recovery_name'");
135 test_recovery_standby('XID + time + name',
136 'standby_8', $node_master, \@recovery_params, "4000", $lsn4);
138 "recovery_target_xid = '$recovery_txid'",
139 "recovery_target_time = '$recovery_time'",
140 "recovery_target_name = '$recovery_name'",
141 "recovery_target_lsn = '$recovery_lsn'",);
142 test_recovery_standby('XID + time + name + LSN',
143 'standby_9', $node_master, \@recovery_params, "5000", $lsn5);