diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/ipc/standby.c | 12 | ||||
-rw-r--r-- | src/test/recovery/t/035_standby_logical_decoding.pl | 56 |
2 files changed, 54 insertions, 14 deletions
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 5acb4508f85..7fa8d9247e0 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -31,6 +31,7 @@ #include "storage/sinvaladt.h" #include "storage/standby.h" #include "utils/hsearch.h" +#include "utils/injection_point.h" #include "utils/ps_status.h" #include "utils/timeout.h" #include "utils/timestamp.h" @@ -1287,6 +1288,17 @@ LogStandbySnapshot(void) Assert(XLogStandbyInfoActive()); +#ifdef USE_INJECTION_POINTS + if (IS_INJECTION_POINT_ATTACHED("skip-log-running-xacts")) + { + /* + * This record could move slot's xmin forward during decoding, leading + * to unpredictable results, so skip it when requested by the test. + */ + return GetInsertRecPtr(); + } +#endif + /* * Get details of any AccessExclusiveLocks being held at the moment. */ diff --git a/src/test/recovery/t/035_standby_logical_decoding.pl b/src/test/recovery/t/035_standby_logical_decoding.pl index ee066626af7..b85a4a4eda6 100644 --- a/src/test/recovery/t/035_standby_logical_decoding.pl +++ b/src/test/recovery/t/035_standby_logical_decoding.pl @@ -10,6 +10,11 @@ use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; use Test::More; +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + my ($stdout, $stderr, $cascading_stdout, $cascading_stderr, $handle); my $node_primary = PostgreSQL::Test::Cluster->new('primary'); @@ -241,16 +246,19 @@ sub check_for_invalidation # VACUUM command, $sql the sql to launch before triggering the vacuum and # $to_vac the relation to vacuum. # -# Note that pg_current_snapshot() is used to get the horizon. It does -# not generate a Transaction/COMMIT WAL record, decreasing the risk of -# seeing a xl_running_xacts that would advance an active replication slot's -# catalog_xmin. Advancing the active replication slot's catalog_xmin -# would break some tests that expect the active slot to conflict with -# the catalog xmin horizon. +# Note that the injection_point avoids seeing a xl_running_xacts that could +# advance an active replication slot's catalog_xmin. Advancing the active +# replication slot's catalog_xmin would break some tests that expect the +# active slot to conflict with the catalog xmin horizon. sub wait_until_vacuum_can_remove { my ($vac_option, $sql, $to_vac) = @_; + # Note that from this point the checkpointer and bgwriter will skip writing + # xl_running_xacts record. + $node_primary->safe_psql('testdb', + "SELECT injection_points_attach('skip-log-running-xacts', 'error');"); + # Get the current xid horizon, my $xid_horizon = $node_primary->safe_psql('testdb', qq[select pg_snapshot_xmin(pg_current_snapshot());]); @@ -268,6 +276,12 @@ sub wait_until_vacuum_can_remove $node_primary->safe_psql( 'testdb', qq[VACUUM $vac_option verbose $to_vac; INSERT INTO flush_wal DEFAULT VALUES;]); + + $node_primary->wait_for_replay_catchup($node_standby); + + # Resume generating the xl_running_xacts record + $node_primary->safe_psql('testdb', + "SELECT injection_points_detach('skip-log-running-xacts');"); } ######################## @@ -285,6 +299,14 @@ autovacuum = off $node_primary->dump_info; $node_primary->start; +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node_primary->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + $node_primary->psql('postgres', q[CREATE DATABASE testdb]); $node_primary->safe_psql('testdb', @@ -528,6 +550,9 @@ is($result, qq(10), 'check replicated inserts after subscription on standby'); $node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub"); $node_subscriber->stop; +# Create the injection_points extension +$node_primary->safe_psql('testdb', 'CREATE EXTENSION injection_points;'); + ################################################## # Recovery conflict: Invalidate conflicting slots, including in-use slots # Scenario 1: hot_standby_feedback off and vacuum FULL @@ -557,8 +582,6 @@ wait_until_vacuum_can_remove( 'full', 'CREATE TABLE conflict_test(x integer, y text); DROP TABLE conflict_test;', 'pg_class'); -$node_primary->wait_for_replay_catchup($node_standby); - # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('vacuum_full_', 1, 'with vacuum FULL on pg_class'); @@ -665,8 +688,6 @@ wait_until_vacuum_can_remove( '', 'CREATE TABLE conflict_test(x integer, y text); DROP TABLE conflict_test;', 'pg_class'); -$node_primary->wait_for_replay_catchup($node_standby); - # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('row_removal_', $logstart, 'with vacuum on pg_class'); @@ -699,8 +720,6 @@ wait_until_vacuum_can_remove( '', 'CREATE ROLE create_trash; DROP ROLE create_trash;', 'pg_authid'); -$node_primary->wait_for_replay_catchup($node_standby); - # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('shared_row_removal_', $logstart, 'with vacuum on pg_authid'); @@ -733,8 +752,6 @@ wait_until_vacuum_can_remove( INSERT INTO conflict_test(x,y) SELECT s, s::text FROM generate_series(1,4) s; UPDATE conflict_test set x=1, y=1;', 'conflict_test'); -$node_primary->wait_for_replay_catchup($node_standby); - # message should not be issued ok( !$node_standby->log_contains( "invalidating obsolete slot \"no_conflict_inactiveslot\"", $logstart), @@ -782,6 +799,13 @@ $logstart = -s $node_standby->logfile; reactive_slots_change_hfs_and_wait_for_xmins('no_conflict_', 'pruning_', 0, 0); +# Injection_point avoids seeing a xl_running_xacts. This is required because if +# it is generated between the last two updates, then the catalog_xmin of the +# active slot could be updated, and hence, the conflict won't occur. See +# comments atop wait_until_vacuum_can_remove. +$node_primary->safe_psql('testdb', + "SELECT injection_points_attach('skip-log-running-xacts', 'error');"); + # This should trigger the conflict $node_primary->safe_psql('testdb', qq[CREATE TABLE prun(id integer, s char(2000)) WITH (fillfactor = 75, user_catalog_table = true);] @@ -794,6 +818,10 @@ $node_primary->safe_psql('testdb', qq[UPDATE prun SET s = 'E';]); $node_primary->wait_for_replay_catchup($node_standby); +# Resume generating the xl_running_xacts record +$node_primary->safe_psql('testdb', + "SELECT injection_points_detach('skip-log-running-xacts');"); + # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('pruning_', $logstart, 'with on-access pruning'); |