1# Test for promotion handling with WAL records generated post-promotion 2# before the first checkpoint is generated. This test case checks for 3# invalid page references at replay based on the minimum consistent 4# recovery point defined. 5use strict; 6use warnings; 7use PostgresNode; 8use TestLib; 9use Test::More tests => 1; 10 11# Initialize primary node 12my $alpha = get_new_node('alpha'); 13$alpha->init(allows_streaming => 1); 14# Setting wal_log_hints to off is important to get invalid page 15# references. 16$alpha->append_conf("postgresql.conf", <<EOF); 17wal_log_hints = off 18EOF 19 20# Start the primary 21$alpha->start; 22 23# setup/start a standby 24$alpha->backup('bkp'); 25my $bravo = get_new_node('bravo'); 26$bravo->init_from_backup($alpha, 'bkp', has_streaming => 1); 27$bravo->append_conf('postgresql.conf', <<EOF); 28checkpoint_timeout=1h 29checkpoint_completion_target=0.9 30EOF 31$bravo->start; 32 33# Dummy table for the upcoming tests. 34$alpha->safe_psql('postgres', 'create table test1 (a int)'); 35$alpha->safe_psql('postgres', 'insert into test1 select generate_series(1, 10000)'); 36 37# take a checkpoint 38$alpha->safe_psql('postgres', 'checkpoint'); 39 40# The following vacuum will set visibility map bits and create 41# problematic WAL records. 42$alpha->safe_psql('postgres', 'vacuum verbose test1'); 43# Wait for last record to have been replayed on the standby. 44$alpha->wait_for_catchup($bravo, 'replay', 45 $alpha->lsn('insert')); 46 47# Now force a checkpoint on the standby. This seems unnecessary but for "some" 48# reason, the previous checkpoint on the primary does not reflect on the standby 49# and without an explicit checkpoint, it may start redo recovery from a much 50# older point, which includes even create table and initial page additions. 51$bravo->safe_psql('postgres', 'checkpoint'); 52 53# Now just use a dummy table and run some operations to move minRecoveryPoint 54# beyond the previous vacuum. 55$alpha->safe_psql('postgres', 'create table test2 (a int, b text)'); 56$alpha->safe_psql('postgres', 'insert into test2 select generate_series(1,10000), md5(random()::text)'); 57$alpha->safe_psql('postgres', 'truncate test2'); 58 59# Wait again for all records to be replayed. 60$alpha->wait_for_catchup($bravo, 'replay', 61 $alpha->lsn('insert')); 62 63# Do the promotion, which reinitializes minRecoveryPoint in the control 64# file so as WAL is replayed up to the end. 65$bravo->promote; 66 67# Truncate the table on the promoted standby, vacuum and extend it 68# again to create new page references. The first post-recovery checkpoint 69# has not happened yet. 70$bravo->safe_psql('postgres', 'truncate test1'); 71$bravo->safe_psql('postgres', 'vacuum verbose test1'); 72$bravo->safe_psql('postgres', 'insert into test1 select generate_series(1,1000)'); 73 74# Now crash-stop the promoted standby and restart. This makes sure that 75# replay does not see invalid page references because of an invalid 76# minimum consistent recovery point. 77$bravo->stop('immediate'); 78$bravo->start; 79 80# Check state of the table after full crash recovery. All its data should 81# be here. 82my $psql_out; 83$bravo->psql( 84 'postgres', 85 "SELECT count(*) FROM test1", 86 stdout => \$psql_out); 87is($psql_out, '1000', "Check that table state is correct"); 88