|
| 1 | +# Test for archive recovery of WAL generated with wal_level=minimal |
| 2 | +use strict; |
| 3 | +use warnings; |
| 4 | +use PostgresNode; |
| 5 | +use TestLib; |
| 6 | +use Test::More tests => 2; |
| 7 | +use Time::HiRes qw(usleep); |
| 8 | + |
| 9 | +# Initialize and start node with wal_level = replica and WAL archiving |
| 10 | +# enabled. |
| 11 | +my $node = get_new_node('orig'); |
| 12 | +$node->init(has_archiving => 1); |
| 13 | +my $replica_config = q[ |
| 14 | +wal_level = replica |
| 15 | +archive_mode = on |
| 16 | +max_wal_senders = 10 |
| 17 | +hot_standby = off |
| 18 | +]; |
| 19 | +$node->append_conf('postgresql.conf', $replica_config); |
| 20 | +$node->start; |
| 21 | + |
| 22 | +# Take backup |
| 23 | +my $backup_name = 'my_backup'; |
| 24 | +$node->backup($backup_name); |
| 25 | + |
| 26 | +# Restart node with wal_level = minimal and WAL archiving disabled |
| 27 | +# to generate WAL with that setting. Note that such WAL has not been |
| 28 | +# archived yet at this moment because WAL archiving is not enabled. |
| 29 | +$node->append_conf( |
| 30 | + 'postgresql.conf', q[ |
| 31 | +wal_level = minimal |
| 32 | +archive_mode = off |
| 33 | +max_wal_senders = 0 |
| 34 | +]); |
| 35 | +$node->restart; |
| 36 | + |
| 37 | +# Restart node with wal_level = replica and WAL archiving enabled |
| 38 | +# to archive WAL previously generated with wal_level = minimal. |
| 39 | +# We ensure the WAL file containing the record indicating the change |
| 40 | +# of wal_level to minimal is archived by checking pg_stat_archiver. |
| 41 | +$node->append_conf('postgresql.conf', $replica_config); |
| 42 | +$node->restart; |
| 43 | + |
| 44 | +# Find next WAL segment to be archived |
| 45 | +my $walfile_to_be_archived = $node->safe_psql('postgres', |
| 46 | + "SELECT pg_walfile_name(pg_current_wal_lsn());"); |
| 47 | + |
| 48 | +# Make WAL segment eligible for archival |
| 49 | +$node->safe_psql('postgres', 'SELECT pg_switch_wal()'); |
| 50 | +my $archive_wait_query |
| 51 | + = "SELECT '$walfile_to_be_archived' <= last_archived_wal FROM pg_stat_archiver;"; |
| 52 | + |
| 53 | +# Wait until the WAL segment has been archived. |
| 54 | +$node->poll_query_until('postgres', $archive_wait_query) |
| 55 | + or die "Timed out while waiting for WAL segment to be archived"; |
| 56 | + |
| 57 | +$node->stop; |
| 58 | + |
| 59 | +# Initialize new node from backup, and start archive recovery. Check that |
| 60 | +# archive recovery fails with an error when it detects the WAL record |
| 61 | +# indicating the change of wal_level to minimal and node stops. |
| 62 | +sub test_recovery_wal_level_minimal |
| 63 | +{ |
| 64 | + my ($node_name, $node_text, $standby_setting) = @_; |
| 65 | + |
| 66 | + my $recovery_node = get_new_node($node_name); |
| 67 | + $recovery_node->init_from_backup( |
| 68 | + $node, $backup_name, |
| 69 | + has_restoring => 1, standby => $standby_setting); |
| 70 | + |
| 71 | + # Use run_log instead of recovery_node->start because this test expects |
| 72 | + # that the server ends with an error during recovery. |
| 73 | + run_log( |
| 74 | + ['pg_ctl','-D', $recovery_node->data_dir, '-l', |
| 75 | + $recovery_node->logfile, 'start']); |
| 76 | + |
| 77 | + # Wait up to 180s for postgres to terminate |
| 78 | + foreach my $i (0 .. 1800) |
| 79 | + { |
| 80 | + last if !-f $recovery_node->data_dir . '/postmaster.pid'; |
| 81 | + usleep(100_000); |
| 82 | + } |
| 83 | + |
| 84 | + # Confirm that the archive recovery fails with an expected error |
| 85 | + my $logfile = slurp_file($recovery_node->logfile()); |
| 86 | + ok( $logfile =~ |
| 87 | + qr/FATAL: WAL was generated with wal_level=minimal, cannot continue recovering/, |
| 88 | + "$node_text ends with an error because it finds WAL generated with wal_level=minimal"); |
| 89 | +} |
| 90 | + |
| 91 | +# Test for archive recovery |
| 92 | +test_recovery_wal_level_minimal('archive_recovery', 'archive recovery', 0); |
| 93 | + |
| 94 | +# Test for standby server |
| 95 | +test_recovery_wal_level_minimal('standby', 'standby', 1); |
0 commit comments