Revive "snapshot too old" with wal_level=minimal and SET TABLESPACE.
authorNoah Misch
Sat, 30 Jan 2021 08:12:18 +0000 (00:12 -0800)
committerNoah Misch
Sat, 30 Jan 2021 08:13:58 +0000 (00:13 -0800)
Given a permanent relation rewritten in the current transaction, the
old_snapshot_threshold mechanism assumed the relation had never been
subject to early pruning.  Hence, a query could fail to report "snapshot
too old" when the rewrite followed an early truncation.  ALTER TABLE SET
TABLESPACE is probably the only rewrite mechanism capable of exposing
this bug.  REINDEX sets indcheckxmin, avoiding the problem.  CLUSTER has
zeroed page LSNs since before old_snapshot_threshold existed, so
old_snapshot_threshold has never cooperated with it.  ALTER TABLE
... SET DATA TYPE makes the table look empty to every past snapshot,
which is strictly worse.  Back-patch to v13, where commit
c6b92041d38512a4176ed76ad06f713d2e6c01a8 broke this.

Kyotaro Horiguchi and Noah Misch

Discussion: https://postgr.es/m/20210113.160705.2225256954956139776[email protected]

src/backend/utils/time/snapmgr.c
src/include/utils/snapmgr.h

index 1c063c592cebbfe05ca46e5bcc9b437d8aa81425..5e3b31ba9027dcfc5268d65655f731357c977f19 100644 (file)
@@ -1777,7 +1777,8 @@ TransactionIdLimitedForOldSnapshots(TransactionId recentXmin,
 {
    if (TransactionIdIsNormal(recentXmin)
        && old_snapshot_threshold >= 0
-       && RelationAllowsEarlyPruning(relation))
+       && RelationAllowsEarlyPruning(relation)
+       && RelationNeedsWAL(relation))
    {
        TimestampTz ts = GetSnapshotCurrentTimestamp();
        TransactionId xlimit = recentXmin;
index b28d13ce841e7be5a6842022e338a152b71ad8ac..ad7c15dc1a2e25fdb42d239a5137f95cc4c186e0 100644 (file)
@@ -37,7 +37,7 @@
  */
 #define RelationAllowsEarlyPruning(rel) \
 ( \
-    RelationNeedsWAL(rel) \
+    (rel)->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT  \
   && !IsCatalogRelation(rel) \
   && !RelationIsAccessibleInLogicalDecoding(rel) \
 )