]> granicus.if.org Git - postgresql/blob - src/test/recovery/t/003_recovery_targets.pl
In tests, await an LSN no later than the recovery target.
[postgresql] / src / test / recovery / t / 003_recovery_targets.pl
1 # Test for recovery targets: name, timestamp, XID
2 use strict;
3 use warnings;
4 use PostgresNode;
5 use TestLib;
6 use Test::More tests => 9;
7
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
12 {
13         my $test_name       = shift;
14         my $node_name       = shift;
15         my $node_master     = shift;
16         my $recovery_params = shift;
17         my $num_rows        = shift;
18         my $until_lsn       = shift;
19
20         my $node_standby = get_new_node($node_name);
21         $node_standby->init_from_backup($node_master, 'my_backup',
22                 has_restoring => 1);
23
24         foreach my $param_item (@$recovery_params)
25         {
26                 $node_standby->append_conf('recovery.conf', qq($param_item));
27         }
28
29         $node_standby->start;
30
31         # Wait until standby has replayed enough data
32         my $caughtup_query =
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";
36
37         # Create some content on master and check its presence in standby
38         my $result =
39           $node_standby->safe_psql('postgres', "SELECT count(*) FROM tab_int");
40         is($result, qq($num_rows), "check standby content for $test_name");
41
42         # Stop standby node
43         $node_standby->teardown_node;
44 }
45
46 # Initialize master node
47 my $node_master = get_new_node('master');
48 $node_master->init(has_archiving => 1, allows_streaming => 1);
49
50 # Start it
51 $node_master->start;
52
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");
57 my $lsn1 =
58   $node_master->safe_psql('postgres', "SELECT pg_current_wal_lsn();");
59
60 # Take backup from which all operations will be run
61 $node_master->backup('my_backup');
62
63 # Insert some data with used as a replay reference, with a recovery
64 # target TXID.
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;
70
71 # More data, with recovery target timestamp
72 $node_master->safe_psql('postgres',
73         "INSERT INTO tab_int VALUES (generate_series(2001,3000))");
74 my $lsn3 =
75   $node_master->safe_psql('postgres', "SELECT pg_current_wal_lsn();");
76 my $recovery_time = $node_master->safe_psql('postgres', "SELECT now()");
77
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";
82 my $lsn4 =
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');");
86
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()");
92
93 $node_master->safe_psql('postgres',
94         "INSERT INTO tab_int VALUES (generate_series(5001,6000))");
95
96 # Force archiving of WAL file
97 $node_master->safe_psql('postgres', "SELECT pg_switch_wal()");
98
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,
105         "2000", $lsn2);
106 @recovery_params = ("recovery_target_time = '$recovery_time'");
107 test_recovery_standby('time', 'standby_3', $node_master, \@recovery_params,
108         "3000", $lsn3);
109 @recovery_params = ("recovery_target_name = '$recovery_name'");
110 test_recovery_standby('name', 'standby_4', $node_master, \@recovery_params,
111         "4000", $lsn4);
112 @recovery_params = ("recovery_target_lsn = '$recovery_lsn'");
113 test_recovery_standby('LSN', 'standby_5', $node_master, \@recovery_params,
114         "5000", $lsn5);
115
116 # Multiple targets
117 # Last entry has priority (note that an array respects the order of items
118 # not hashes).
119 @recovery_params = (
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);
125 @recovery_params = (
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);
131 @recovery_params = (
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);
137 @recovery_params = (
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);