]> granicus.if.org Git - postgresql/blob - src/test/recovery/t/008_fsm_truncation.pl
Fix WAL-logging of FSM and VM truncation.
[postgresql] / src / test / recovery / t / 008_fsm_truncation.pl
1 # Test WAL replay of FSM changes.
2 #
3 # FSM changes don't normally need to be WAL-logged, except for truncation.
4 # The FSM mustn't return a page that doesn't exist (anymore).
5 use strict;
6 use warnings;
7
8 use PostgresNode;
9 use TestLib;
10 use Test::More tests => 1;
11
12 my $node_master = get_new_node('master');
13 $node_master->init(allows_streaming => 1);
14
15 $node_master->append_conf('postgresql.conf', qq{
16 fsync = on
17 wal_level = replica
18 wal_log_hints = on
19 max_prepared_transactions = 5
20 autovacuum = off
21 });
22
23 # Create a master node and its standby, initializing both with some data
24 # at the same time.
25 $node_master->start;
26
27 $node_master->backup('master_backup');
28 my $node_standby = get_new_node('standby');
29 $node_standby->init_from_backup($node_master, 'master_backup',
30         has_streaming => 1);
31 $node_standby->start;
32
33 $node_master->psql('postgres', qq{
34 create table testtab (a int, b char(100));
35 insert into testtab select generate_series(1,1000), 'foo';
36 insert into testtab select generate_series(1,1000), 'foo';
37 delete from testtab where ctid > '(8,0)';
38 });
39
40 # Take a lock on the table to prevent following vacuum from truncating it
41 $node_master->psql('postgres', qq{
42 begin;
43 lock table testtab in row share mode;
44 prepare transaction 'p1';
45 });
46
47 # Vacuum, update FSM without truncation
48 $node_master->psql('postgres', 'vacuum verbose testtab');
49
50 # Force a checkpoint
51 $node_master->psql('postgres', 'checkpoint');
52
53 # Now do some more insert/deletes, another vacuum to ensure full-page writes
54 # are done
55 $node_master->psql('postgres', qq{
56 insert into testtab select generate_series(1,1000), 'foo';
57 delete from testtab where ctid > '(8,0)';
58 vacuum verbose testtab;
59 });
60
61 # Ensure all buffers are now clean on the standby
62 $node_standby->psql('postgres', 'checkpoint');
63
64 # Release the lock, vacuum again which should lead to truncation
65 $node_master->psql('postgres', qq{
66 rollback prepared 'p1';
67 vacuum verbose testtab;
68 });
69
70 $node_master->psql('postgres', 'checkpoint');
71 my $until_lsn =
72         $node_master->safe_psql('postgres', "SELECT pg_current_xlog_location();");
73
74 # Wait long enough for standby to receive and apply all WAL
75 my $caughtup_query =
76         "SELECT '$until_lsn'::pg_lsn <= pg_last_xlog_replay_location()";
77 $node_standby->poll_query_until('postgres', $caughtup_query)
78         or die "Timed out while waiting for standby to catch up";
79
80 # Promote the standby
81 $node_standby->promote;
82 $node_standby->poll_query_until('postgres',
83         "SELECT NOT pg_is_in_recovery()")
84   or die "Timed out while waiting for promotion of standby";
85 $node_standby->psql('postgres', 'checkpoint');
86
87 # Restart to discard in-memory copy of FSM
88 $node_standby->restart;
89
90 # Insert should work on standby
91 is($node_standby->psql('postgres',
92    qq{insert into testtab select generate_series(1,1000), 'foo';}),
93    0, 'INSERT succeeds with truncated relation FSM');