Fix catalog lookup with the wrong snapshot during logical decoding

Enterprise / PostgreSQL - Amit Kapila [postgresql.org] - 11 August 2022 04:39 UTC

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.

7f13ac8123 Fix catalog lookup with the wrong snapshot during logical decoding.
contrib/test_decoding/Makefile | 2 +-
.../expected/catalog_change_snapshot.out | 44 ++++
.../specs/catalog_change_snapshot.spec | 39 +++
src/backend/replication/logical/decode.c | 3 +-
src/backend/replication/logical/reorderbuffer.c | 71 +++++-
src/backend/replication/logical/snapbuild.c | 273 ++++++++++++++-------
src/include/replication/reorderbuffer.h | 12 +
src/include/replication/snapbuild.h | 2 +-
8 files changed, 353 insertions(+), 93 deletions(-)

Upstream: git.postgresql.org


  • Share