From ea7e504d9ac90ba0dfa8731f7b3465e07d19baf8 Mon Sep 17 00:00:00 2001 From: bovenshi Date: Fri, 25 Nov 2022 15:42:01 +0800 Subject: [PATCH] Fix snapshot builder's state after restoring snapshot from disk. Set snapshot builder's state after restoring snapshot from disk, since consistent snapshots have no next phase. Per reports from bowenshi. Discussion: https://www.postgresql.org/message-id/17695-6be9277c9295985f%40postgresql.org --- src/backend/replication/logical/snapbuild.c | 6 ++ src/test/recovery/t/034_replication_snapbuild.pl | 100 +++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/test/recovery/t/034_replication_snapbuild.pl diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index b5b018e..03e7458 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1964,6 +1964,12 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) /* consistent snapshots have no next phase */ Assert(ondisk.builder.next_phase_at == InvalidTransactionId); + /* + * We are now in consistent point and have no next phase, copy the state + * from the snapshot in disk. + */ + builder->next_phase_at = ondisk.builder.next_phase_at; + /* ok, we think the snapshot is sensible, copy over everything important */ builder->xmin = ondisk.builder.xmin; builder->xmax = ondisk.builder.xmax; diff --git a/src/test/recovery/t/034_replication_snapbuild.pl b/src/test/recovery/t/034_replication_snapbuild.pl new file mode 100644 index 0000000..9a40f25 --- /dev/null +++ b/src/test/recovery/t/034_replication_snapbuild.pl @@ -0,0 +1,100 @@ +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +# Test replication snapshot rebuild. +use strict; +use warnings; +use TestLib; +use PostgresNode; +use Test::More; +use DBI; +use Test::More tests => 1; + +# set slot number +my $slot_num = 100; + +# initialize master node +my $master = get_new_node('master'); +$master->init; +$master->append_conf( + 'postgresql.conf', qq( +wal_level=logical +max_connections=1000 +max_worker_processes=500 +max_wal_senders=500 +max_replication_slots=500 +max_logical_replication_workers=500 +log_error_verbosity = verbose +log_statement = all +)); +$master->start; +my $master_port = $master->port; + +# master init +for (my $i = 0; $i<$slot_num; $i = $i+1) +{ + my $table_name=qq(t_$i); + my $pub_name=qq(pub_$i); + $master->safe_psql('postgres', "create table $table_name(a int);"); + $master->safe_psql('postgres', "create publication $pub_name for table $table_name;"); +} + +# create subscription +my $subscriber = get_new_node('subscriber'); +$subscriber->init; +$subscriber->append_conf( + 'postgresql.conf', qq( +wal_level=logical +max_connections=1000 +max_worker_processes=500 +max_replication_slots=500 +log_error_verbosity = verbose +max_logical_replication_workers=500 +log_statement = all +)); +$subscriber->start; + +# subscriber init +for (my $i = 0; $i<$slot_num; $i = $i+1) +{ + my $table_name=qq(t_$i); + my $pub_name=qq(pub_$i); + my $sub_name=qq(sub_$i); + + $subscriber->safe_psql('postgres', + "create table $table_name(a int);"); +} + +my $script = $master->basedir . '/pgbench_script'; +for (my $i = 0; $i<$slot_num; $i = $i+1) +{ + my $table_name=qq(t_$i); + + append_to_file($script, + "INSERT INTO $table_name SELECT FROM generate_series(1,100);"); +} + +my $pid = fork(); +if ($pid == 0) +{ + sleep(1); + for (my $i = 0; $i<$slot_num; $i = $i+1) + { + my $pub_name=qq(pub_$i); + my $sub_name=qq(sub_$i); + + $subscriber->safe_psql('postgres', + "create subscription $sub_name connection 'port=$master_port dbname=postgres user=postgres' publication $pub_name;"); + } + exec "echo", "\nbye\n"; +} +elsif ($pid < 0) +{ + die "failed to fork new process"; +} + +$master->run_log( + [qw(pgbench --no-vacuum --client=10 -U postgres + -T 25 --file), $script ]); + +my $result = $master->safe_psql('postgres', "select count(*) from pg_replication_slots;"); +is($result, qq($slot_num), "Create slots successfully.") \ No newline at end of file -- 2.9.3