aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2024-06-27 21:06:32 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2024-06-27 21:09:15 +0300
commit5dea6628b32d8092e789d9e31509ed74840a271e (patch)
treefd5e77cdf78e3a60cd27215e1b87c483373b71d3 /src/test
parent266454f192e8f67e8e5e8e9f7667d7c8c77de232 (diff)
downloadpostgresql-5dea6628b32d8092e789d9e31509ed74840a271e.tar.gz
postgresql-5dea6628b32d8092e789d9e31509ed74840a271e.zip
Fix MVCC bug with prepared xact with subxacts on standby
We did not recover the subtransaction IDs of prepared transactions when starting a hot standby from a shutdown checkpoint. As a result, such subtransactions were considered as aborted, rather than in-progress. That would lead to hint bits being set incorrectly, and the subtransactions suddenly becoming visible to old snapshots when the prepared transaction was committed. To fix, update pg_subtrans with prepared transactions's subxids when starting hot standby from a shutdown checkpoint. The snapshots taken from that state need to be marked as "suboverflowed", so that we also check the pg_subtrans. Backport to all supported versions. Discussion: https://www.postgresql.org/message-id/6b852e98-2d49-4ca1-9e95-db419a2696e0@iki.fi
Diffstat (limited to 'src/test')
-rw-r--r--src/test/recovery/t/009_twophase.pl48
1 files changed, 47 insertions, 1 deletions
diff --git a/src/test/recovery/t/009_twophase.pl b/src/test/recovery/t/009_twophase.pl
index 4a79c5ebfdb..308014a9876 100644
--- a/src/test/recovery/t/009_twophase.pl
+++ b/src/test/recovery/t/009_twophase.pl
@@ -4,7 +4,7 @@ use warnings;
use PostgresNode;
use TestLib;
-use Test::More tests => 24;
+use Test::More tests => 27;
my $psql_out = '';
my $psql_rc = '';
@@ -306,6 +306,52 @@ $cur_standby->start;
$cur_master->psql('postgres', "COMMIT PREPARED 'xact_009_12'");
###############################################################################
+# Check visibility of prepared transactions in standby after a restart while
+# primary is down.
+###############################################################################
+
+$cur_master->psql(
+ 'postgres', "
+ CREATE TABLE t_009_tbl_standby_mvcc (id int, msg text);
+ BEGIN;
+ INSERT INTO t_009_tbl_standby_mvcc VALUES (1, 'issued to ${cur_master_name}');
+ SAVEPOINT s1;
+ INSERT INTO t_009_tbl_standby_mvcc VALUES (2, 'issued to ${cur_master_name}');
+ PREPARE TRANSACTION 'xact_009_standby_mvcc';
+ ");
+$cur_master->stop;
+$cur_standby->restart;
+
+# Acquire a snapshot in standby, before we commit the prepared transaction
+my $standby_session = $cur_standby->background_psql('postgres', on_error_die => 1);
+$standby_session->query_safe("BEGIN ISOLATION LEVEL REPEATABLE READ");
+$psql_out = $standby_session->query_safe(
+ "SELECT count(*) FROM t_009_tbl_standby_mvcc");
+is($psql_out, '0',
+ "Prepared transaction not visible in standby before commit");
+
+# Commit the transaction in primary
+$cur_master->start;
+$cur_master->psql('postgres', "
+SET synchronous_commit='remote_apply'; -- To ensure the standby is caught up
+COMMIT PREPARED 'xact_009_standby_mvcc';
+");
+
+# Still not visible to the old snapshot
+$psql_out = $standby_session->query_safe(
+ "SELECT count(*) FROM t_009_tbl_standby_mvcc");
+is($psql_out, '0',
+ "Committed prepared transaction not visible to old snapshot in standby");
+
+# Is visible to a new snapshot
+$standby_session->query_safe("COMMIT");
+$psql_out = $standby_session->query_safe(
+ "SELECT count(*) FROM t_009_tbl_standby_mvcc");
+is($psql_out, '2',
+ "Committed prepared transaction is visible to new snapshot in standby");
+$standby_session->quit;
+
+###############################################################################
# Check for a lock conflict between prepared transaction with DDL inside and
# replay of XLOG_STANDBY_LOCK wal record.
###############################################################################