10
10
use PostgreSQL::Test::Utils;
11
11
use Test::More;
12
12
13
+ if ($ENV {enable_injection_points } ne ' yes' )
14
+ {
15
+ plan skip_all => ' Injection points not supported by this build' ;
16
+ }
17
+
13
18
my ($stdout , $stderr , $cascading_stdout , $cascading_stderr , $handle );
14
19
15
20
my $node_primary = PostgreSQL::Test::Cluster-> new(' primary' );
@@ -241,16 +246,19 @@ sub check_for_invalidation
241
246
# VACUUM command, $sql the sql to launch before triggering the vacuum and
242
247
# $to_vac the relation to vacuum.
243
248
#
244
- # Note that pg_current_snapshot() is used to get the horizon. It does
245
- # not generate a Transaction/COMMIT WAL record, decreasing the risk of
246
- # seeing a xl_running_xacts that would advance an active replication slot's
247
- # catalog_xmin. Advancing the active replication slot's catalog_xmin
248
- # would break some tests that expect the active slot to conflict with
249
- # the catalog xmin horizon.
249
+ # Note that the injection_point avoids seeing a xl_running_xacts that could
250
+ # advance an active replication slot's catalog_xmin. Advancing the active
251
+ # replication slot's catalog_xmin would break some tests that expect the
252
+ # active slot to conflict with the catalog xmin horizon.
250
253
sub wait_until_vacuum_can_remove
251
254
{
252
255
my ($vac_option , $sql , $to_vac ) = @_ ;
253
256
257
+ # Note that from this point the checkpointer and bgwriter will skip writing
258
+ # xl_running_xacts record.
259
+ $node_primary -> safe_psql(' testdb' ,
260
+ " SELECT injection_points_attach('skip-log-running-xacts', 'error');" );
261
+
254
262
# Get the current xid horizon,
255
263
my $xid_horizon = $node_primary -> safe_psql(' testdb' ,
256
264
qq[ select pg_snapshot_xmin(pg_current_snapshot());] );
@@ -268,6 +276,12 @@ sub wait_until_vacuum_can_remove
268
276
$node_primary -> safe_psql(
269
277
' testdb' , qq[ VACUUM $vac_option verbose $to_vac ;
270
278
INSERT INTO flush_wal DEFAULT VALUES;] );
279
+
280
+ $node_primary -> wait_for_replay_catchup($node_standby );
281
+
282
+ # Resume generating the xl_running_xacts record
283
+ $node_primary -> safe_psql(' testdb' ,
284
+ " SELECT injection_points_detach('skip-log-running-xacts');" );
271
285
}
272
286
273
287
# #######################
@@ -285,6 +299,14 @@ sub wait_until_vacuum_can_remove
285
299
$node_primary -> dump_info;
286
300
$node_primary -> start;
287
301
302
+ # Check if the extension injection_points is available, as it may be
303
+ # possible that this script is run with installcheck, where the module
304
+ # would not be installed by default.
305
+ if (!$node_primary -> check_extension(' injection_points' ))
306
+ {
307
+ plan skip_all => ' Extension injection_points not installed' ;
308
+ }
309
+
288
310
$node_primary -> psql(' postgres' , q[ CREATE DATABASE testdb] );
289
311
290
312
$node_primary -> safe_psql(' testdb' ,
@@ -528,6 +550,9 @@ sub wait_until_vacuum_can_remove
528
550
$node_subscriber -> safe_psql(' postgres' , " DROP SUBSCRIPTION tap_sub" );
529
551
$node_subscriber -> stop;
530
552
553
+ # Create the injection_points extension
554
+ $node_primary -> safe_psql(' testdb' , ' CREATE EXTENSION injection_points;' );
555
+
531
556
# #################################################
532
557
# Recovery conflict: Invalidate conflicting slots, including in-use slots
533
558
# Scenario 1: hot_standby_feedback off and vacuum FULL
@@ -557,8 +582,6 @@ sub wait_until_vacuum_can_remove
557
582
' full' , ' CREATE TABLE conflict_test(x integer, y text);
558
583
DROP TABLE conflict_test;' , ' pg_class' );
559
584
560
- $node_primary -> wait_for_replay_catchup($node_standby );
561
-
562
585
# Check invalidation in the logfile and in pg_stat_database_conflicts
563
586
check_for_invalidation(' vacuum_full_' , 1, ' with vacuum FULL on pg_class' );
564
587
@@ -665,8 +688,6 @@ sub wait_until_vacuum_can_remove
665
688
' ' , ' CREATE TABLE conflict_test(x integer, y text);
666
689
DROP TABLE conflict_test;' , ' pg_class' );
667
690
668
- $node_primary -> wait_for_replay_catchup($node_standby );
669
-
670
691
# Check invalidation in the logfile and in pg_stat_database_conflicts
671
692
check_for_invalidation(' row_removal_' , $logstart , ' with vacuum on pg_class' );
672
693
@@ -699,8 +720,6 @@ sub wait_until_vacuum_can_remove
699
720
' ' , ' CREATE ROLE create_trash;
700
721
DROP ROLE create_trash;' , ' pg_authid' );
701
722
702
- $node_primary -> wait_for_replay_catchup($node_standby );
703
-
704
723
# Check invalidation in the logfile and in pg_stat_database_conflicts
705
724
check_for_invalidation(' shared_row_removal_' , $logstart ,
706
725
' with vacuum on pg_authid' );
@@ -733,8 +752,6 @@ sub wait_until_vacuum_can_remove
733
752
INSERT INTO conflict_test(x,y) SELECT s, s::text FROM generate_series(1,4) s;
734
753
UPDATE conflict_test set x=1, y=1;' , ' conflict_test' );
735
754
736
- $node_primary -> wait_for_replay_catchup($node_standby );
737
-
738
755
# message should not be issued
739
756
ok( !$node_standby -> log_contains(
740
757
" invalidating obsolete slot \" no_conflict_inactiveslot\" " , $logstart ),
@@ -782,6 +799,13 @@ sub wait_until_vacuum_can_remove
782
799
reactive_slots_change_hfs_and_wait_for_xmins(' no_conflict_' , ' pruning_' , 0,
783
800
0);
784
801
802
+ # Injection_point avoids seeing a xl_running_xacts. This is required because if
803
+ # it is generated between the last two updates, then the catalog_xmin of the
804
+ # active slot could be updated, and hence, the conflict won't occur. See
805
+ # comments atop wait_until_vacuum_can_remove.
806
+ $node_primary -> safe_psql(' testdb' ,
807
+ " SELECT injection_points_attach('skip-log-running-xacts', 'error');" );
808
+
785
809
# This should trigger the conflict
786
810
$node_primary -> safe_psql(' testdb' ,
787
811
qq[ CREATE TABLE prun(id integer, s char(2000)) WITH (fillfactor = 75, user_catalog_table = true);]
@@ -794,6 +818,10 @@ sub wait_until_vacuum_can_remove
794
818
795
819
$node_primary -> wait_for_replay_catchup($node_standby );
796
820
821
+ # Resume generating the xl_running_xacts record
822
+ $node_primary -> safe_psql(' testdb' ,
823
+ " SELECT injection_points_detach('skip-log-running-xacts');" );
824
+
797
825
# Check invalidation in the logfile and in pg_stat_database_conflicts
798
826
check_for_invalidation(' pruning_' , $logstart , ' with on-access pruning' );
799
827
0 commit comments