]> granicus.if.org Git - postgresql/commitdiff
Ignore CatalogSnapshot when checking COPY FREEZE prerequisites.
authorNoah Misch <noah@leadboat.com>
Sun, 5 Nov 2017 17:25:52 +0000 (09:25 -0800)
committerNoah Misch <noah@leadboat.com>
Sun, 5 Nov 2017 17:25:59 +0000 (09:25 -0800)
This restores the ability, essentially lost in commit
ffaa44cb559db332baeee7d25dedd74a61974203, to use COPY FREEZE under
REPEATABLE READ isolation.  Back-patch to 9.4, like that commit.

Reviewed by Tom Lane.

Discussion: https://postgr.es/m/CA+TgmoahWDm-7fperBxzU9uZ99LPMUmEpSXLTw9TmrOgzwnORw@mail.gmail.com

src/backend/commands/copy.c
src/backend/utils/time/snapmgr.c

index ef81e3be7119136b024cbedf4f1c6112e1d66cbd..ef301b6328addad48f15bd445edcfb9ce8d8cbfa 100644 (file)
@@ -2392,13 +2392,25 @@ CopyFrom(CopyState cstate)
        /*
         * Optimize if new relfilenode was created in this subxact or one of its
         * committed children and we won't see those rows later as part of an
-        * earlier scan or command. This ensures that if this subtransaction
-        * aborts then the frozen rows won't be visible after xact cleanup. Note
+        * earlier scan or command. The subxact test ensures that if this subxact
+        * aborts then the frozen rows won't be visible after xact cleanup.  Note
         * that the stronger test of exactly which subtransaction created it is
-        * crucial for correctness of this optimization.
+        * crucial for correctness of this optimization. The test for an earlier
+        * scan or command tolerates false negatives. FREEZE causes other sessions
+        * to see rows they would not see under MVCC, and a false negative merely
+        * spreads that anomaly to the current session.
         */
        if (cstate->freeze)
        {
+               /*
+                * Tolerate one registration for the benefit of FirstXactSnapshot.
+                * Scan-bearing queries generally create at least two registrations,
+                * though relying on that is fragile, as is ignoring ActiveSnapshot.
+                * Clear CatalogSnapshot to avoid counting its registration.  We'll
+                * still detect ongoing catalog scans, each of which separately
+                * registers the snapshot it uses.
+                */
+               InvalidateCatalogSnapshot();
                if (!ThereAreNoPriorRegisteredSnapshots() || !ThereAreNoReadyPortals())
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
index 294ab705f1d3965deac1074c4fc1e4ccd0abc366..addf87dc3bb61ac1c2be4ea12580f7775c9a7a8f 100644 (file)
@@ -1645,6 +1645,14 @@ DeleteAllExportedSnapshotFiles(void)
        FreeDir(s_dir);
 }
 
+/*
+ * ThereAreNoPriorRegisteredSnapshots
+ *             Is the registered snapshot count less than or equal to one?
+ *
+ * Don't use this to settle important decisions.  While zero registrations and
+ * no ActiveSnapshot would confirm a certain idleness, the system makes no
+ * guarantees about the significance of one registered snapshot.
+ */
 bool
 ThereAreNoPriorRegisteredSnapshots(void)
 {