]> granicus.if.org Git - postgresql/blob - src/test/recovery/t/007_sync_rep.pl
Don't fall off the end of perl functions
[postgresql] / src / test / recovery / t / 007_sync_rep.pl
1 # Minimal test testing synchronous replication sync_state transition
2 use strict;
3 use warnings;
4 use PostgresNode;
5 use TestLib;
6 use Test::More tests => 11;
7
8 # Query checking sync_priority and sync_state of each standby
9 my $check_sql =
10   "SELECT application_name, sync_priority, sync_state FROM pg_stat_replication ORDER BY application_name;";
11
12 # Check that sync_state of each standby is expected (waiting till it is).
13 # If $setting is given, synchronous_standby_names is set to it and
14 # the configuration file is reloaded before the test.
15 sub test_sync_state
16 {
17         my ($self, $expected, $msg, $setting) = @_;
18
19         if (defined($setting))
20         {
21                 $self->psql('postgres',
22                         "ALTER SYSTEM SET synchronous_standby_names = '$setting';");
23                 $self->reload;
24         }
25
26         ok($self->poll_query_until('postgres', $check_sql, $expected), $msg);
27         return;
28 }
29
30 # Initialize master node
31 my $node_master = get_new_node('master');
32 $node_master->init(allows_streaming => 1);
33 $node_master->start;
34 my $backup_name = 'master_backup';
35
36 # Take backup
37 $node_master->backup($backup_name);
38
39 # Create standby1 linking to master
40 my $node_standby_1 = get_new_node('standby1');
41 $node_standby_1->init_from_backup($node_master, $backup_name,
42         has_streaming => 1);
43 $node_standby_1->start;
44
45 # Create standby2 linking to master
46 my $node_standby_2 = get_new_node('standby2');
47 $node_standby_2->init_from_backup($node_master, $backup_name,
48         has_streaming => 1);
49 $node_standby_2->start;
50
51 # Create standby3 linking to master
52 my $node_standby_3 = get_new_node('standby3');
53 $node_standby_3->init_from_backup($node_master, $backup_name,
54         has_streaming => 1);
55 $node_standby_3->start;
56
57 # Check that sync_state is determined correctly when
58 # synchronous_standby_names is specified in old syntax.
59 test_sync_state(
60         $node_master, qq(standby1|1|sync
61 standby2|2|potential
62 standby3|0|async),
63         'old syntax of synchronous_standby_names',
64         'standby1,standby2');
65
66 # Check that all the standbys are considered as either sync or
67 # potential when * is specified in synchronous_standby_names.
68 # Note that standby1 is chosen as sync standby because
69 # it's stored in the head of WalSnd array which manages
70 # all the standbys though they have the same priority.
71 test_sync_state(
72         $node_master, qq(standby1|1|sync
73 standby2|1|potential
74 standby3|1|potential),
75         'asterisk in synchronous_standby_names',
76         '*');
77
78 # Stop and start standbys to rearrange the order of standbys
79 # in WalSnd array. Now, if standbys have the same priority,
80 # standby2 is selected preferentially and standby3 is next.
81 $node_standby_1->stop;
82 $node_standby_2->stop;
83 $node_standby_3->stop;
84
85 $node_standby_2->start;
86 $node_standby_3->start;
87
88 # Specify 2 as the number of sync standbys.
89 # Check that two standbys are in 'sync' state.
90 test_sync_state(
91         $node_master, qq(standby2|2|sync
92 standby3|3|sync),
93         '2 synchronous standbys',
94         '2(standby1,standby2,standby3)');
95
96 # Start standby1
97 $node_standby_1->start;
98
99 # Create standby4 linking to master
100 my $node_standby_4 = get_new_node('standby4');
101 $node_standby_4->init_from_backup($node_master, $backup_name,
102         has_streaming => 1);
103 $node_standby_4->start;
104
105 # Check that standby1 and standby2 whose names appear earlier in
106 # synchronous_standby_names are considered as sync. Also check that
107 # standby3 appearing later represents potential, and standby4 is
108 # in 'async' state because it's not in the list.
109 test_sync_state(
110         $node_master, qq(standby1|1|sync
111 standby2|2|sync
112 standby3|3|potential
113 standby4|0|async),
114         '2 sync, 1 potential, and 1 async');
115
116 # Check that sync_state of each standby is determined correctly
117 # when num_sync exceeds the number of names of potential sync standbys
118 # specified in synchronous_standby_names.
119 test_sync_state(
120         $node_master, qq(standby1|0|async
121 standby2|4|sync
122 standby3|3|sync
123 standby4|1|sync),
124         'num_sync exceeds the num of potential sync standbys',
125         '6(standby4,standby0,standby3,standby2)');
126
127 # The setting that * comes before another standby name is acceptable
128 # but does not make sense in most cases. Check that sync_state is
129 # chosen properly even in case of that setting.
130 # The priority of standby2 should be 2 because it matches * first.
131 test_sync_state(
132         $node_master, qq(standby1|1|sync
133 standby2|2|sync
134 standby3|2|potential
135 standby4|2|potential),
136         'asterisk comes before another standby name',
137         '2(standby1,*,standby2)');
138
139 # Check that the setting of '2(*)' chooses standby2 and standby3 that are stored
140 # earlier in WalSnd array as sync standbys.
141 test_sync_state(
142         $node_master, qq(standby1|1|potential
143 standby2|1|sync
144 standby3|1|sync
145 standby4|1|potential),
146         'multiple standbys having the same priority are chosen as sync',
147         '2(*)');
148
149 # Stop Standby3 which is considered in 'sync' state.
150 $node_standby_3->stop;
151
152 # Check that the state of standby1 stored earlier in WalSnd array than
153 # standby4 is transited from potential to sync.
154 test_sync_state(
155         $node_master, qq(standby1|1|sync
156 standby2|1|sync
157 standby4|1|potential),
158         'potential standby found earlier in array is promoted to sync');
159
160 # Check that standby1 and standby2 are chosen as sync standbys
161 # based on their priorities.
162 test_sync_state(
163         $node_master, qq(standby1|1|sync
164 standby2|2|sync
165 standby4|0|async),
166         'priority-based sync replication specified by FIRST keyword',
167         'FIRST 2(standby1, standby2)');
168
169 # Check that all the listed standbys are considered as candidates
170 # for sync standbys in a quorum-based sync replication.
171 test_sync_state(
172         $node_master, qq(standby1|1|quorum
173 standby2|1|quorum
174 standby4|0|async),
175         '2 quorum and 1 async',
176         'ANY 2(standby1, standby2)');
177
178 # Start Standby3 which will be considered in 'quorum' state.
179 $node_standby_3->start;
180
181 # Check that the setting of 'ANY 2(*)' chooses all standbys as
182 # candidates for quorum sync standbys.
183 test_sync_state(
184         $node_master, qq(standby1|1|quorum
185 standby2|1|quorum
186 standby3|1|quorum
187 standby4|1|quorum),
188         'all standbys are considered as candidates for quorum sync standbys',
189         'ANY 2(*)');