2024-01-31 16:29:22 +01:00
|
|
|
# Copyright (c) 2021-2024, PostgreSQL Global Development Group
|
2024-01-11 18:47:28 +01:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use File::Compare;
|
|
|
|
use PostgreSQL::Test::Cluster;
|
|
|
|
use PostgreSQL::Test::Utils;
|
|
|
|
use Test::More;
|
|
|
|
|
|
|
|
# Set up a new database instance.
|
|
|
|
my $node1 = PostgreSQL::Test::Cluster->new('node1');
|
|
|
|
$node1->init(has_archiving => 1, allows_streaming => 1);
|
|
|
|
$node1->append_conf('postgresql.conf', 'summarize_wal = on');
|
|
|
|
$node1->start;
|
|
|
|
|
|
|
|
# Create a table and insert a few test rows into it. VACUUM FREEZE it so that
|
|
|
|
# autovacuum doesn't induce any future modifications unexpectedly. Then
|
|
|
|
# trigger a checkpoint.
|
|
|
|
$node1->safe_psql('postgres', <<EOM);
|
|
|
|
CREATE TABLE mytable (a int, b text);
|
|
|
|
INSERT INTO mytable
|
|
|
|
SELECT
|
|
|
|
g, random()::text||random()::text||random()::text||random()::text
|
|
|
|
FROM
|
|
|
|
generate_series(1, 400) g;
|
|
|
|
VACUUM FREEZE;
|
2024-01-31 16:12:53 +01:00
|
|
|
EOM
|
|
|
|
|
|
|
|
# Record the current WAL insert LSN.
|
|
|
|
my $base_lsn = $node1->safe_psql('postgres', <<EOM);
|
|
|
|
SELECT pg_current_wal_insert_lsn()
|
|
|
|
EOM
|
|
|
|
note("just after insert, WAL insert LSN is $base_lsn");
|
|
|
|
|
|
|
|
# Now perform a CHECKPOINT.
|
|
|
|
$node1->safe_psql('postgres', <<EOM);
|
2024-01-11 18:47:28 +01:00
|
|
|
CHECKPOINT;
|
|
|
|
EOM
|
|
|
|
|
2024-01-31 16:12:53 +01:00
|
|
|
# Wait for a new summary to show up, one that includes the inserts we just did.
|
|
|
|
my $result = $node1->poll_query_until('postgres', <<EOM);
|
2024-01-11 18:47:28 +01:00
|
|
|
SELECT EXISTS (
|
|
|
|
SELECT * from pg_available_wal_summaries()
|
2024-01-31 16:12:53 +01:00
|
|
|
WHERE end_lsn >= '$base_lsn'
|
2024-01-11 18:47:28 +01:00
|
|
|
)
|
|
|
|
EOM
|
2024-01-31 16:12:53 +01:00
|
|
|
ok($result, "WAL summarization caught up after insert");
|
2024-01-11 18:47:28 +01:00
|
|
|
|
2024-01-31 16:12:53 +01:00
|
|
|
# Get a list of what summaries we now have.
|
|
|
|
my $progress = $node1->safe_psql('postgres', <<EOM);
|
2024-01-11 18:47:28 +01:00
|
|
|
SELECT summarized_tli, summarized_lsn FROM pg_get_wal_summarizer_state()
|
|
|
|
EOM
|
2024-01-31 16:12:53 +01:00
|
|
|
my ($summarized_tli, $summarized_lsn) = split(/\|/, $progress);
|
2024-01-11 18:47:28 +01:00
|
|
|
note("after insert, summarized TLI $summarized_tli through $summarized_lsn");
|
2024-01-26 19:25:19 +01:00
|
|
|
note_wal_summary_dir("after insert", $node1);
|
2024-01-11 18:47:28 +01:00
|
|
|
|
|
|
|
# Update a row in the first block of the table and trigger a checkpoint.
|
|
|
|
$node1->safe_psql('postgres', <<EOM);
|
|
|
|
UPDATE mytable SET b = 'abcdefghijklmnopqrstuvwxyz' WHERE a = 2;
|
|
|
|
CHECKPOINT;
|
|
|
|
EOM
|
|
|
|
|
2024-01-31 16:12:53 +01:00
|
|
|
# Wait for a new summary to show up.
|
|
|
|
$result = $node1->poll_query_until('postgres', <<EOM);
|
2024-01-11 18:47:28 +01:00
|
|
|
SELECT EXISTS (
|
|
|
|
SELECT * from pg_available_wal_summaries()
|
|
|
|
WHERE tli = $summarized_tli AND end_lsn > '$summarized_lsn'
|
|
|
|
)
|
|
|
|
EOM
|
2024-01-31 16:12:53 +01:00
|
|
|
ok($result, "got new WAL summary after update");
|
2024-01-11 18:47:28 +01:00
|
|
|
|
2024-01-15 17:50:44 +01:00
|
|
|
# Figure out the exact details for the new summary file.
|
2024-01-11 18:47:28 +01:00
|
|
|
my $details = $node1->safe_psql('postgres', <<EOM);
|
|
|
|
SELECT tli, start_lsn, end_lsn from pg_available_wal_summaries()
|
|
|
|
WHERE tli = $summarized_tli AND end_lsn > '$summarized_lsn'
|
|
|
|
EOM
|
2024-01-31 16:12:53 +01:00
|
|
|
my @lines = split(/\n/, $details);
|
|
|
|
is(0+@lines, 1, "got exactly one new WAL summary");
|
|
|
|
my ($tli, $start_lsn, $end_lsn) = split(/\|/, $lines[0]);
|
2024-01-11 18:47:28 +01:00
|
|
|
note("examining summary for TLI $tli from $start_lsn to $end_lsn");
|
2024-01-26 19:25:19 +01:00
|
|
|
note_wal_summary_dir("after new summary", $node1);
|
2024-01-11 18:47:28 +01:00
|
|
|
|
|
|
|
# Reconstruct the full pathname for the WAL summary file.
|
|
|
|
my $filename = sprintf "%s/pg_wal/summaries/%08s%08s%08s%08s%08s.summary",
|
|
|
|
$node1->data_dir, $tli,
|
|
|
|
split(m@/@, $start_lsn),
|
|
|
|
split(m@/@, $end_lsn);
|
|
|
|
ok(-f $filename, "WAL summary file exists");
|
2024-01-26 19:25:19 +01:00
|
|
|
note_wal_summary_dir("after existence check", $node1);
|
2024-01-11 18:47:28 +01:00
|
|
|
|
2024-01-31 16:12:53 +01:00
|
|
|
# Run pg_walsummary on it. We expect exactly two blocks to be modified,
|
|
|
|
# block 0 and one other.
|
2024-01-11 21:01:51 +01:00
|
|
|
my ($stdout, $stderr) = run_command([ 'pg_walsummary', '-i', $filename ]);
|
2024-01-31 16:12:53 +01:00
|
|
|
note($stdout);
|
|
|
|
@lines = split(/\n/, $stdout);
|
2024-01-11 18:47:28 +01:00
|
|
|
like($stdout, qr/FORK main: block 0$/m, "stdout shows block 0 modified");
|
|
|
|
is($stderr, '', 'stderr is empty');
|
2024-01-31 16:12:53 +01:00
|
|
|
is(0+@lines, 2, "UPDATE modified 2 blocks");
|
2024-01-26 19:25:19 +01:00
|
|
|
note_wal_summary_dir("after pg_walsummary run", $node1);
|
2024-01-11 18:47:28 +01:00
|
|
|
|
|
|
|
done_testing();
|
2024-01-26 19:25:19 +01:00
|
|
|
|
|
|
|
# XXX. Temporary debugging code.
|
|
|
|
sub note_wal_summary_dir
|
|
|
|
{
|
|
|
|
my ($flair, $node) = @_;
|
|
|
|
|
|
|
|
my $wsdir = sprintf "%s/pg_wal/summaries", $node->data_dir;
|
|
|
|
my @wsfiles = grep { $_ ne '.' && $_ ne '..' } slurp_dir($wsdir);
|
|
|
|
note("$flair pg_wal/summaries has: @wsfiles");
|
|
|
|
}
|