From 63b416b6b0065e6e178913a916a2f366f4f0d1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Nordstr=C3=B6m?= Date: Fri, 10 Mar 2023 13:15:02 +0100 Subject: [PATCH] Use consistent snapshots when scanning metadata Invalidate the catalog snapshot in the scanner to ensure that any lookups into `pg_catalog` uses a snapshot that is consistent with the snapshot used to scan TimescaleDB metadata. This fixes an issue where a chunk could be looked up without having a proper relid filled in, causing an assertion failure (`ASSERT_IS_VALID_CHUNK`). When a chunk is scanned and found (in `chunk_tuple_found()`), the Oid of the chunk table is filled in using `get_relname_relid()`, which could return InvalidOid due to use of a different snapshot when scanning `pg_class`. Calling `InvalidateCatalogSnapshot()` before starting the metadata scan in `Scanner` ensures the pg_catalog snapshot used is refreshed. Due to the difficulty of reproducing this MVCC issue, no regression or isolation test is provided, but it is easy to hit this bug when doing highly concurrent COPY:s into a distributed hypertable. --- CHANGELOG.md | 1 + src/scanner.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d4c344cc..b945d823c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ accidentally triggering the load of a previous DB version.** * #5410 Fix file trailer handling in the COPY fetcher * #5233 Out of on_proc_exit slots on guc license change * #5427 Handle user-defined FDW options properly +* #5428 Use consistent snapshots when scanning metadata * #5442 Decompression may have lost DEFAULT values * #5446 Add checks for malloc failure in libpq calls diff --git a/src/scanner.c b/src/scanner.c index e04241e72..a1887b9c0 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -221,6 +221,20 @@ prepare_scan(ScannerCtx *ctx) */ MemoryContext oldmcxt = MemoryContextSwitchTo(ctx->internal.scan_mcxt); ctx->snapshot = RegisterSnapshot(GetSnapshotData(SnapshotSelf)); + /* + * Invalidate the PG catalog snapshot to ensure it is refreshed and + * up-to-date with the snapshot used to scan TimescaleDB + * metadata. Since TimescaleDB metadata is often joined with PG + * catalog data (e.g., calling get_relname_relid() to fill in chunk + * table Oid), this avoids any potential problems where the different + * snapshots used to scan TimescaleDB metadata and PG catalog metadata + * aren't in sync. + * + * Ideally, a catalog snapshot would be used to scan TimescaleDB + * metadata, but that will change the behavior of chunk creation in + * SERIALIZED mode, as described above. + */ + InvalidateCatalogSnapshot(); ctx->internal.registered_snapshot = true; MemoryContextSwitchTo(oldmcxt); }