From: Michael Paquier Date: Mon, 13 Jul 2026 23:00:46 +0000 (+0900) Subject: Add recovery test for missing redo segment with backup_label X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8f71f64deee6747ad9dea18819018b25424d61e5;p=thirdparty%2Fpostgresql.git Add recovery test for missing redo segment with backup_label This commit adds a test case for early startup where a backup_label file uses a checkpoint LSN and a redo LSN located in two different segments, where the segment of the redo LSN is missing. This code has never been covered, and is complex enough that a test case is going to be useful in the long-term. Nitin has proposed a more complex approach than what is added by this commit, by forcing a reuse of the injection points to produce a split between redo and checkpoint. This commit relies on the checkpoint and redo LSNs generated by the first steps of the test, combined with a generated backup_label, making the whole cheaper. Author: Nitin Jadhav Author: Michael Paquier Discussion: https://postgr.es/m/CAMm1aWZ9Tv=Wrx52_2Ppw+6ULf_twRZuQm=ZWLA_a-kXWykHkQ@mail.gmail.com --- diff --git a/src/test/recovery/t/050_redo_segment_missing.pl b/src/test/recovery/t/050_redo_segment_missing.pl index e07ff0c72fe..16b83d51d01 100644 --- a/src/test/recovery/t/050_redo_segment_missing.pl +++ b/src/test/recovery/t/050_redo_segment_missing.pl @@ -6,6 +6,7 @@ use strict; use warnings FATAL => 'all'; +use File::Copy qw(copy); use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; use Test::More; @@ -114,4 +115,47 @@ ok( $logfile =~ qr/FATAL: .* could not find redo location .* referenced by checkpoint record at .*/, "ends with FATAL because it could not find redo location"); +# Test for a missing redo record specified in a backup_label file. +# This reuses the redo and checkpoint LSNs calculated previously and +# writes a fake backup_label into a fresh node. +my $node_label = PostgreSQL::Test::Cluster->new('testnode_backup_label'); +$node_label->init; +$node_label->append_conf('postgresql.conf', "archive_mode = off"); + +# Copy pg_control from the original node so the new node recognizes the +# system identifier and timeline. +copy( + $node->data_dir . '/global/pg_control', + $node_label->data_dir . '/global/pg_control' +) or BAIL_OUT("could not copy pg_control"); + +# Provide only the checkpoint segment, omitting the redo segment. +copy( + $node->data_dir . "/pg_wal/$checkpoint_walfile_name", + $node_label->data_dir . "/pg_wal/$checkpoint_walfile_name" +) or BAIL_OUT("could not copy checkpoint WAL segment"); + +# Write a fake backup_label with valid checkpoint and redo LSNs. +open my $fh, '>', $node_label->data_dir . '/backup_label' + or BAIL_OUT("could not create backup_label"); +binmode $fh; +print $fh "START WAL LOCATION: $redo_lsn (file $redo_walfile_name)\n"; +print $fh "CHECKPOINT LOCATION: $checkpoint_lsn\n"; +print $fh "BACKUP METHOD: pg_backup_start\n"; +print $fh "BACKUP FROM: primary\n"; +close $fh; + +run_log( + [ + 'pg_ctl', + '--pgdata' => $node_label->data_dir, + '--log' => $node_label->logfile, + 'start', + ]); + +my $logfile_label = slurp_file($node_label->logfile()); +ok( $logfile_label =~ + qr/FATAL: .* could not find redo location .* referenced by checkpoint record at .*/, + "ends with FATAL for missing redo location with backup_label"); + done_testing();