2022-08-29 04:40:10 +02:00
|
|
|
Parsed test spec with 3 sessions
|
Fix catalog lookup with the wrong snapshot during logical decoding.
Previously, we relied on HEAP2_NEW_CID records and XACT_INVALIDATION
records to know if the transaction has modified the catalog, and that
information is not serialized to snapshot. Therefore, after the restart,
if the logical decoding decodes only the commit record of the transaction
that has actually modified a catalog, we will miss adding its XID to the
snapshot. Thus, we will end up looking at catalogs with the wrong
snapshot.
To fix this problem, this change adds the list of transaction IDs and
sub-transaction IDs, that have modified catalogs and are running during
snapshot serialization, to the serialized snapshot. After restart or
otherwise, when we restore from such a serialized snapshot, the
corresponding list is restored in memory. Now, when decoding a COMMIT
record, we check both the list and the ReorderBuffer to see if the
transaction has modified catalogs.
Since this adds additional information to the serialized snapshot, we
cannot backpatch it. For back branches, we took another approach.
We remember the last-running-xacts list of the decoded RUNNING_XACTS
record after restoring the previously serialized snapshot. Then, we mark
the transaction as containing catalog changes if it's in the list of
initial running transactions and its commit record has
XACT_XINFO_HAS_INVALS. This doesn't require any file format changes but
the transaction will end up being added to the snapshot even if it has
only relcache invalidations. But that won't be a problem since we use
snapshot built during decoding only to read system catalogs.
This commit bumps SNAPBUILD_VERSION because of a change in SnapBuild.
Reported-by: Mike Oh
Author: Masahiko Sawada
Reviewed-by: Amit Kapila, Shi yu, Takamichi Osumi, Kyotaro Horiguchi, Bertrand Drouvot, Ahsan Hadi
Backpatch-through: 10
Discussion: https://postgr.es/m/81D0D8B0-E7C4-4999-B616-1E5004DBDCD2%40amazon.com
2022-08-11 06:39:24 +02:00
|
|
|
|
|
|
|
starting permutation: s0_init s0_begin s0_savepoint s0_truncate s1_checkpoint s1_get_changes s0_commit s0_begin s0_insert s1_checkpoint s1_get_changes s0_commit s1_get_changes
|
|
|
|
step s0_init: SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding');
|
|
|
|
?column?
|
|
|
|
--------
|
|
|
|
init
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
step s0_begin: BEGIN;
|
|
|
|
step s0_savepoint: SAVEPOINT sp1;
|
|
|
|
step s0_truncate: TRUNCATE tbl1;
|
|
|
|
step s1_checkpoint: CHECKPOINT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
----
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
step s0_commit: COMMIT;
|
|
|
|
step s0_begin: BEGIN;
|
|
|
|
step s0_insert: INSERT INTO tbl1 VALUES (1);
|
|
|
|
step s1_checkpoint: CHECKPOINT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
---------------------------------------
|
|
|
|
BEGIN
|
|
|
|
table public.tbl1: TRUNCATE: (no-flags)
|
|
|
|
COMMIT
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
step s0_commit: COMMIT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
-------------------------------------------------------------
|
|
|
|
BEGIN
|
|
|
|
table public.tbl1: INSERT: val1[integer]:1 val2[integer]:null
|
|
|
|
COMMIT
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
?column?
|
|
|
|
--------
|
|
|
|
stop
|
|
|
|
(1 row)
|
|
|
|
|
2022-08-29 04:40:10 +02:00
|
|
|
|
|
|
|
starting permutation: s0_init s0_begin s0_truncate s2_begin s2_truncate s1_checkpoint s1_get_changes s0_commit s0_begin s0_insert s1_checkpoint s1_get_changes s2_commit s1_checkpoint s1_get_changes s0_commit s1_get_changes
|
|
|
|
step s0_init: SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding');
|
|
|
|
?column?
|
|
|
|
--------
|
|
|
|
init
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
step s0_begin: BEGIN;
|
|
|
|
step s0_truncate: TRUNCATE tbl1;
|
|
|
|
step s2_begin: BEGIN;
|
|
|
|
step s2_truncate: TRUNCATE tbl2;
|
|
|
|
step s1_checkpoint: CHECKPOINT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
----
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
step s0_commit: COMMIT;
|
|
|
|
step s0_begin: BEGIN;
|
|
|
|
step s0_insert: INSERT INTO tbl1 VALUES (1);
|
|
|
|
step s1_checkpoint: CHECKPOINT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
---------------------------------------
|
|
|
|
BEGIN
|
|
|
|
table public.tbl1: TRUNCATE: (no-flags)
|
|
|
|
COMMIT
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
step s2_commit: COMMIT;
|
|
|
|
step s1_checkpoint: CHECKPOINT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
---------------------------------------
|
|
|
|
BEGIN
|
|
|
|
table public.tbl2: TRUNCATE: (no-flags)
|
|
|
|
COMMIT
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
step s0_commit: COMMIT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
-------------------------------------------------------------
|
|
|
|
BEGIN
|
|
|
|
table public.tbl1: INSERT: val1[integer]:1 val2[integer]:null
|
|
|
|
COMMIT
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
?column?
|
|
|
|
--------
|
|
|
|
stop
|
|
|
|
(1 row)
|
|
|
|
|
2022-10-20 05:19:48 +02:00
|
|
|
|
|
|
|
starting permutation: s0_init s0_begin s0_savepoint s0_insert s1_checkpoint s1_get_changes s0_insert2 s0_commit s0_begin s0_insert s1_checkpoint s1_get_changes s0_commit s1_get_changes
|
|
|
|
step s0_init: SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding');
|
|
|
|
?column?
|
|
|
|
--------
|
|
|
|
init
|
|
|
|
(1 row)
|
|
|
|
|
|
|
|
step s0_begin: BEGIN;
|
|
|
|
step s0_savepoint: SAVEPOINT sp1;
|
|
|
|
step s0_insert: INSERT INTO tbl1 VALUES (1);
|
|
|
|
step s1_checkpoint: CHECKPOINT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
----
|
|
|
|
(0 rows)
|
|
|
|
|
|
|
|
step s0_insert2: INSERT INTO user_cat VALUES (1);
|
|
|
|
step s0_commit: COMMIT;
|
|
|
|
step s0_begin: BEGIN;
|
|
|
|
step s0_insert: INSERT INTO tbl1 VALUES (1);
|
|
|
|
step s1_checkpoint: CHECKPOINT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
-------------------------------------------------------------
|
|
|
|
BEGIN
|
|
|
|
table public.tbl1: INSERT: val1[integer]:1 val2[integer]:null
|
|
|
|
table public.user_cat: INSERT: val1[integer]:1
|
|
|
|
COMMIT
|
|
|
|
(4 rows)
|
|
|
|
|
|
|
|
step s0_commit: COMMIT;
|
|
|
|
step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0');
|
|
|
|
data
|
|
|
|
-------------------------------------------------------------
|
|
|
|
BEGIN
|
|
|
|
table public.tbl1: INSERT: val1[integer]:1 val2[integer]:null
|
|
|
|
COMMIT
|
|
|
|
(3 rows)
|
|
|
|
|
|
|
|
?column?
|
|
|
|
--------
|
|
|
|
stop
|
|
|
|
(1 row)
|
|
|
|
|