mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Additional tests for subtransactions in recovery
Tests for normal and prepared transactions Author: Nikhil Sontakke, placed in new test file by me
This commit is contained in:
		@@ -4,7 +4,7 @@ use warnings;
 | 
			
		||||
 | 
			
		||||
use PostgresNode;
 | 
			
		||||
use TestLib;
 | 
			
		||||
use Test::More tests => 13;
 | 
			
		||||
use Test::More tests => 12;
 | 
			
		||||
 | 
			
		||||
# Setup master node
 | 
			
		||||
my $node_master = get_new_node("master");
 | 
			
		||||
@@ -283,40 +283,3 @@ $node_master->psql('postgres', "
 | 
			
		||||
$node_slave->psql('postgres', "SELECT count(*) FROM pg_prepared_xacts",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '0', "Replay prepared transaction with DDL");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
# Check that replay will correctly set SUBTRANS and properly advance nextXid
 | 
			
		||||
# so that it won't conflict with savepoint xids.
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
	BEGIN;
 | 
			
		||||
	DELETE FROM t_009_tbl;
 | 
			
		||||
	INSERT INTO t_009_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s1;
 | 
			
		||||
	INSERT INTO t_009_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s2;
 | 
			
		||||
	INSERT INTO t_009_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s3;
 | 
			
		||||
	INSERT INTO t_009_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s4;
 | 
			
		||||
	INSERT INTO t_009_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s5;
 | 
			
		||||
	INSERT INTO t_009_tbl VALUES (43);
 | 
			
		||||
	PREPARE TRANSACTION 'xact_009_1';
 | 
			
		||||
	CHECKPOINT;");
 | 
			
		||||
 | 
			
		||||
$node_master->stop;
 | 
			
		||||
$node_master->start;
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
	-- here we can get xid of previous savepoint if nextXid
 | 
			
		||||
	-- wasn't properly advanced
 | 
			
		||||
	BEGIN;
 | 
			
		||||
	INSERT INTO t_009_tbl VALUES (142);
 | 
			
		||||
	ROLLBACK;
 | 
			
		||||
	COMMIT PREPARED 'xact_009_1';");
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "SELECT count(*) FROM t_009_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '6', "Check nextXid handling for prepared subtransactions");
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										197
									
								
								src/test/recovery/t/012_subtransactions.pl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								src/test/recovery/t/012_subtransactions.pl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
			
		||||
# Tests dedicated to subtransactions in recovery
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
 | 
			
		||||
use PostgresNode;
 | 
			
		||||
use TestLib;
 | 
			
		||||
use Test::More tests => 12;
 | 
			
		||||
 | 
			
		||||
# Setup master node
 | 
			
		||||
my $node_master = get_new_node("master");
 | 
			
		||||
$node_master->init(allows_streaming => 1);
 | 
			
		||||
$node_master->append_conf('postgresql.conf', qq(
 | 
			
		||||
	max_prepared_transactions = 10
 | 
			
		||||
	log_checkpoints = true
 | 
			
		||||
));
 | 
			
		||||
$node_master->start;
 | 
			
		||||
$node_master->backup('master_backup');
 | 
			
		||||
$node_master->psql('postgres', "CREATE TABLE t_012_tbl (id int)");
 | 
			
		||||
 | 
			
		||||
# Setup slave node
 | 
			
		||||
my $node_slave = get_new_node('slave');
 | 
			
		||||
$node_slave->init_from_backup($node_master, 'master_backup', has_streaming => 1);
 | 
			
		||||
$node_slave->start;
 | 
			
		||||
 | 
			
		||||
# Switch to synchronous replication
 | 
			
		||||
$node_master->append_conf('postgresql.conf', qq(
 | 
			
		||||
	synchronous_standby_names = '*'
 | 
			
		||||
));
 | 
			
		||||
$node_master->psql('postgres', "SELECT pg_reload_conf()");
 | 
			
		||||
 | 
			
		||||
my $psql_out = '';
 | 
			
		||||
my $psql_rc = '';
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
# Check that replay will correctly set SUBTRANS and properly advance nextXid
 | 
			
		||||
# so that it won't conflict with savepoint xids.
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
	BEGIN;
 | 
			
		||||
	DELETE FROM t_012_tbl;
 | 
			
		||||
	INSERT INTO t_012_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s1;
 | 
			
		||||
	INSERT INTO t_012_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s2;
 | 
			
		||||
	INSERT INTO t_012_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s3;
 | 
			
		||||
	INSERT INTO t_012_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s4;
 | 
			
		||||
	INSERT INTO t_012_tbl VALUES (43);
 | 
			
		||||
	SAVEPOINT s5;
 | 
			
		||||
	INSERT INTO t_012_tbl VALUES (43);
 | 
			
		||||
	PREPARE TRANSACTION 'xact_012_1';
 | 
			
		||||
	CHECKPOINT;");
 | 
			
		||||
 | 
			
		||||
$node_master->stop;
 | 
			
		||||
$node_master->start;
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
	-- here we can get xid of previous savepoint if nextXid
 | 
			
		||||
	-- wasn't properly advanced
 | 
			
		||||
	BEGIN;
 | 
			
		||||
	INSERT INTO t_012_tbl VALUES (142);
 | 
			
		||||
	ROLLBACK;
 | 
			
		||||
	COMMIT PREPARED 'xact_012_1';");
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "SELECT count(*) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '6', "Check nextXid handling for prepared subtransactions");
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
# Check that replay will correctly set 2PC with more than
 | 
			
		||||
# PGPROC_MAX_CACHED_SUBXIDS subtransations and also show data properly
 | 
			
		||||
# on promotion
 | 
			
		||||
###############################################################################
 | 
			
		||||
$node_master->psql('postgres', "DELETE FROM t_012_tbl");
 | 
			
		||||
 | 
			
		||||
# Function borrowed from src/test/regress/sql/hs_primary_extremes.sql
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
    CREATE OR REPLACE FUNCTION hs_subxids (n integer)
 | 
			
		||||
    RETURNS void
 | 
			
		||||
    LANGUAGE plpgsql
 | 
			
		||||
    AS \$\$
 | 
			
		||||
    BEGIN
 | 
			
		||||
        IF n <= 0 THEN RETURN; END IF;
 | 
			
		||||
        INSERT INTO t_012_tbl VALUES (n);
 | 
			
		||||
        PERFORM hs_subxids(n - 1);
 | 
			
		||||
        RETURN;
 | 
			
		||||
    EXCEPTION WHEN raise_exception THEN NULL; END;
 | 
			
		||||
    \$\$;");
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
	BEGIN;
 | 
			
		||||
	SELECT hs_subxids(127);
 | 
			
		||||
	COMMIT;");
 | 
			
		||||
$node_master->wait_for_catchup($node_slave, 'replay', $node_master->lsn('insert'));
 | 
			
		||||
$node_slave->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '8128', "Visible");
 | 
			
		||||
$node_master->stop;
 | 
			
		||||
$node_slave->promote;
 | 
			
		||||
$node_slave->poll_query_until('postgres',
 | 
			
		||||
	"SELECT NOT pg_is_in_recovery()")
 | 
			
		||||
  or die "Timed out while waiting for promotion of standby";
 | 
			
		||||
 | 
			
		||||
$node_slave->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '8128', "Visible");
 | 
			
		||||
 | 
			
		||||
# restore state
 | 
			
		||||
($node_master, $node_slave) = ($node_slave, $node_master);
 | 
			
		||||
$node_slave->enable_streaming($node_master);
 | 
			
		||||
$node_slave->append_conf('recovery.conf', qq(
 | 
			
		||||
recovery_target_timeline='latest'
 | 
			
		||||
));
 | 
			
		||||
$node_slave->start;
 | 
			
		||||
$node_slave->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '8128', "Visible");
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "DELETE FROM t_012_tbl");
 | 
			
		||||
 | 
			
		||||
# Function borrowed from src/test/regress/sql/hs_primary_extremes.sql
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
    CREATE OR REPLACE FUNCTION hs_subxids (n integer)
 | 
			
		||||
    RETURNS void
 | 
			
		||||
    LANGUAGE plpgsql
 | 
			
		||||
    AS \$\$
 | 
			
		||||
    BEGIN
 | 
			
		||||
        IF n <= 0 THEN RETURN; END IF;
 | 
			
		||||
        INSERT INTO t_012_tbl VALUES (n);
 | 
			
		||||
        PERFORM hs_subxids(n - 1);
 | 
			
		||||
        RETURN;
 | 
			
		||||
    EXCEPTION WHEN raise_exception THEN NULL; END;
 | 
			
		||||
    \$\$;");
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
	BEGIN;
 | 
			
		||||
	SELECT hs_subxids(127);
 | 
			
		||||
	PREPARE TRANSACTION 'xact_012_1';");
 | 
			
		||||
$node_master->wait_for_catchup($node_slave, 'replay', $node_master->lsn('insert'));
 | 
			
		||||
$node_slave->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '-1', "Not visible");
 | 
			
		||||
$node_master->stop;
 | 
			
		||||
$node_slave->promote;
 | 
			
		||||
$node_slave->poll_query_until('postgres',
 | 
			
		||||
	"SELECT NOT pg_is_in_recovery()")
 | 
			
		||||
  or die "Timed out while waiting for promotion of standby";
 | 
			
		||||
 | 
			
		||||
$node_slave->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '-1', "Not visible");
 | 
			
		||||
 | 
			
		||||
# restore state
 | 
			
		||||
($node_master, $node_slave) = ($node_slave, $node_master);
 | 
			
		||||
$node_slave->enable_streaming($node_master);
 | 
			
		||||
$node_slave->append_conf('recovery.conf', qq(
 | 
			
		||||
recovery_target_timeline='latest'
 | 
			
		||||
));
 | 
			
		||||
$node_slave->start;
 | 
			
		||||
$psql_rc = $node_master->psql('postgres', "COMMIT PREPARED 'xact_012_1'");
 | 
			
		||||
is($psql_rc, '0', "Restore of PGPROC_MAX_CACHED_SUBXIDS+ prepared transaction on promoted slave");
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '8128', "Visible");
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "DELETE FROM t_012_tbl");
 | 
			
		||||
$node_master->psql('postgres', "
 | 
			
		||||
	BEGIN;
 | 
			
		||||
	SELECT hs_subxids(201);
 | 
			
		||||
	PREPARE TRANSACTION 'xact_012_1';");
 | 
			
		||||
$node_master->wait_for_catchup($node_slave, 'replay', $node_master->lsn('insert'));
 | 
			
		||||
$node_slave->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '-1', "Not visible");
 | 
			
		||||
$node_master->stop;
 | 
			
		||||
$node_slave->promote;
 | 
			
		||||
$node_slave->poll_query_until('postgres',
 | 
			
		||||
	"SELECT NOT pg_is_in_recovery()")
 | 
			
		||||
  or die "Timed out while waiting for promotion of standby";
 | 
			
		||||
 | 
			
		||||
$node_slave->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '-1', "Not visible");
 | 
			
		||||
 | 
			
		||||
# restore state
 | 
			
		||||
($node_master, $node_slave) = ($node_slave, $node_master);
 | 
			
		||||
$node_slave->enable_streaming($node_master);
 | 
			
		||||
$node_slave->append_conf('recovery.conf', qq(
 | 
			
		||||
recovery_target_timeline='latest'
 | 
			
		||||
));
 | 
			
		||||
$node_slave->start;
 | 
			
		||||
$psql_rc = $node_master->psql('postgres', "ROLLBACK PREPARED 'xact_012_1'");
 | 
			
		||||
is($psql_rc, '0', "Rollback of PGPROC_MAX_CACHED_SUBXIDS+ prepared transaction on promoted slave");
 | 
			
		||||
 | 
			
		||||
$node_master->psql('postgres', "SELECT coalesce(sum(id),-1) FROM t_012_tbl",
 | 
			
		||||
	  stdout => \$psql_out);
 | 
			
		||||
is($psql_out, '-1', "Not visible");
 | 
			
		||||
		Reference in New Issue
	
	Block a user