# Copyright (c) 2025-2026, PostgreSQL Global Development Group # # This test aims to validate two things: (1) that the calculated truncation # block never exceeds the segment size and (2) that the correct limit block # length is calculated for the VM fork.
use strict;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Backup locations
my $backup_path = $primary->backup_dir;
my $full_backup = "$backup_path/full";
# To avoid using up lots of disk space in the CI/buildfarm environment, this # test will only find the issue when run with a small RELSEG_SIZE. As of this # writing, one of the CI runs is configured using --with-segsize-blocks=6, and # we aim to have this test check for the issue only in that configuration.
my $target_blocks = 6;
my $block_size = $primary->safe_psql('postgres', "SELECT current_setting('block_size')::int;");
# We'll have two blocks more than the target number of blocks (one will # survive the subsequent truncation).
my $target_rows = int($target_blocks + 2);
my $rows_after_truncation = int($target_rows - 1);
# Create a test table. STORAGE PLAIN prevents compression and TOASTing of # repetitive data, ensuring predictable row sizes.
$primary->safe_psql( 'postgres', q{
CREATE TABLE t (
id int,
data text STORAGE PLAIN
) WITH (autovacuum_enabled = false);
});
# The tuple size should be enough to prevent two tuples from being on the same # page. Since the template string has a length of 32 bytes, it's enough to # repeat it (block_size / (2*32)) times.
$primary->safe_psql( 'postgres', "INSERT INTO t
SELECT i,
repeat('0123456789ABCDEF0123456789ABCDEF', ($block_size / (2*32)))
FROM generate_series(1, $target_rows) i;"
);
# Make sure hint bits are set.
$primary->safe_psql('postgres', 'VACUUM t;');
# Verify that the relation is as large as was desired.
my $t_blocks = $primary->safe_psql('postgres', "SELECT pg_relation_size('t') / current_setting('block_size')::int;");
cmp_ok($t_blocks, '>', $target_blocks, 'target block size exceeded');
# Take a full base backup
$primary->backup('full');
# Delete rows at the logical end of the table, creating removable pages.
$primary->safe_psql('postgres', "DELETE FROM t WHERE id > ($rows_after_truncation);");
# VACUUM the table. TRUNCATE is enabled by default, and is just mentioned here # for emphasis.
$primary->safe_psql('postgres', 'VACUUM (TRUNCATE) t;');
# Verify expected length after truncation.
$t_blocks = $primary->safe_psql('postgres', "SELECT pg_relation_size('t') / current_setting('block_size')::int;");
is($t_blocks, $rows_after_truncation, 'post-truncation row count as expected');
cmp_ok($t_blocks, '>', $target_blocks, 'post-truncation block count as expected');
# Take an incremental backup based on the full backup manifest
$primary->backup('incr',
backup_options => [ '--incremental', "$full_backup/backup_manifest" ]);
# We used to have a bug where the wrong limit block was calculated for the # VM fork, so verify that the WAL summary records the correct VM fork # truncation limit. We can't just check whether the restored VM fork is # the right size on disk, because it's so small that the incremental backup # code will send the entire file.
my $relfilenode = $primary->safe_psql('postgres', "SELECT pg_relation_filenode('t');");
my $vm_limits = $primary->safe_psql('postgres', "SELECT string_agg(relblocknumber::text, ',')
FROM pg_available_wal_summaries() s,
pg_wal_summary_contents(s.tli, s.start_lsn, s.end_lsn) c
WHERE c.relfilenode = $relfilenode
AND c.relforknumber = 2
AND c.is_limit_block;");
is($vm_limits, '1', 'WAL summary has correct VM fork truncation limit');
# Combine full and incremental backups. Before the fix, this failed because # the INCREMENTAL file header contained an incorrect truncation_block value.
my $restored = PostgreSQL::Test::Cluster->new('node2');
$restored->init_from_backup($primary, 'incr', combine_with_prior => ['full']);
$restored->start();
# Check that the restored table contains the correct number of rows
my $restored_count =
$restored->safe_psql('postgres', "SELECT count(*) FROM t;");
is($restored_count, $rows_after_truncation, 'Restored backup has correct row count');
$primary->stop;
$restored->stop;
done_testing();
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.