mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-25 12:17:20 +02:00
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
40 lines
1.7 KiB
Ruby
40 lines
1.7 KiB
Ruby
# Test decoding only the commit record of the transaction that have
|
|
# modified catalogs.
|
|
setup
|
|
{
|
|
DROP TABLE IF EXISTS tbl1;
|
|
CREATE TABLE tbl1 (val1 integer, val2 integer);
|
|
}
|
|
|
|
teardown
|
|
{
|
|
DROP TABLE tbl1;
|
|
SELECT 'stop' FROM pg_drop_replication_slot('isolation_slot');
|
|
}
|
|
|
|
session "s0"
|
|
setup { SET synchronous_commit=on; }
|
|
step "s0_init" { SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding'); }
|
|
step "s0_begin" { BEGIN; }
|
|
step "s0_savepoint" { SAVEPOINT sp1; }
|
|
step "s0_truncate" { TRUNCATE tbl1; }
|
|
step "s0_insert" { INSERT INTO tbl1 VALUES (1); }
|
|
step "s0_commit" { COMMIT; }
|
|
|
|
session "s1"
|
|
setup { SET synchronous_commit=on; }
|
|
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'); }
|
|
|
|
# For the transaction that TRUNCATEd the table tbl1, the last decoding decodes
|
|
# only its COMMIT record, because it starts from the RUNNING_XACTS record emitted
|
|
# during the first checkpoint execution. This transaction must be marked as
|
|
# containing catalog changes while decoding the COMMIT record and the decoding
|
|
# of the INSERT record must read the pg_class with the correct historic snapshot.
|
|
#
|
|
# Note that in a case where bgwriter wrote the RUNNING_XACTS record between "s0_commit"
|
|
# and "s0_begin", this doesn't happen as the decoding starts from the RUNNING_XACTS
|
|
# record written by bgwriter. One might think we can either stop the bgwriter or
|
|
# increase LOG_SNAPSHOT_INTERVAL_MS but it's not practical via tests.
|
|
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"
|