Skip to content

Commit 16f4312

Browse files
committed
Fix oldest xmin and LSN computation across repslots after advancing
Advancing a replication slot did not recompute the oldest xmin and LSN values across replication slots, preventing resource removal like segments not recycled at checkpoint time. The original commit that introduced the slot advancing in 9c7d06d never did the update of those oldest values, and b0afdca removed this code. This commit adds a TAP test to check segment recycling with advancing for physical slots, enforcing an extra segment switch before advancing to check if the segment gets correctly recycled after a checkpoint. Reported-by: Andres Freund Reviewed-by: Alexey Kondratov, Kyptaro Horiguchi Discussion: https://postgr.es/m/20200609171904.kpltxxvjzislidks@alap3.anarazel.de Backpatch-through: 11
1 parent 812a84d commit 16f4312

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

src/backend/replication/slotfuncs.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,13 @@ pg_replication_slot_advance(PG_FUNCTION_ARGS)
581581
values[0] = NameGetDatum(&MyReplicationSlot->data.name);
582582
nulls[0] = false;
583583

584+
/*
585+
* Recompute the minimum LSN and xmin across all slots to adjust with the
586+
* advancing potentially done.
587+
*/
588+
ReplicationSlotsComputeRequiredXmin(false);
589+
ReplicationSlotsComputeRequiredLSN();
590+
584591
ReplicationSlotRelease();
585592

586593
/* Return the reached position. */

src/test/recovery/t/001_stream_rep.pl

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use warnings;
44
use PostgresNode;
55
use TestLib;
6-
use Test::More tests => 34;
6+
use Test::More tests => 35;
77

88
# Initialize master node
99
my $node_master = get_new_node('master');
@@ -345,14 +345,27 @@ sub replay_check
345345
is($catalog_xmin, '',
346346
'catalog xmin of cascaded slot still null with hs_feedback reset');
347347

348+
$node_standby_1->stop;
349+
350+
# Drop any existing slots on the primary, for the follow-up tests.
351+
$node_master->safe_psql('postgres',
352+
"SELECT pg_drop_replication_slot(slot_name) FROM pg_replication_slots;");
353+
348354
# Test physical slot advancing and its durability. Create a new slot on
349355
# the primary, not used by any of the standbys. This reserves WAL at creation.
350356
my $phys_slot = 'phys_slot';
351357
$node_master->safe_psql('postgres',
352358
"SELECT pg_create_physical_replication_slot('$phys_slot', true);");
359+
# Generate some WAL, and switch to a new segment, used to check that
360+
# the previous segment is correctly getting recycled as the slot advancing
361+
# would recompute the minimum LSN calculated across all slots.
362+
my $segment_removed = $node_master->safe_psql('postgres',
363+
'SELECT pg_walfile_name(pg_current_wal_lsn())');
364+
chomp($segment_removed);
353365
$node_master->psql('postgres', "
354366
CREATE TABLE tab_phys_slot (a int);
355-
INSERT INTO tab_phys_slot VALUES (generate_series(1,10));");
367+
INSERT INTO tab_phys_slot VALUES (generate_series(1,10));
368+
SELECT pg_switch_wal();");
356369
my $current_lsn = $node_master->safe_psql('postgres',
357370
"SELECT pg_current_wal_lsn();");
358371
chomp($current_lsn);
@@ -369,3 +382,9 @@ sub replay_check
369382
chomp($phys_restart_lsn_post);
370383
ok(($phys_restart_lsn_pre cmp $phys_restart_lsn_post) == 0,
371384
"physical slot advance persists across restarts");
385+
386+
# Check if the previous segment gets correctly recycled after the
387+
# server stopped cleanly, causing a shutdown checkpoint to be generated.
388+
my $master_data = $node_master->data_dir;
389+
ok(!-f "$master_data/pg_wal/$segment_removed",
390+
"WAL segment $segment_removed recycled after physical slot advancing");

0 commit comments

Comments
 (0)