Commit bab3a714 authored by Noah Misch's avatar Noah Misch

Ignore CatalogSnapshot when checking COPY FREEZE prerequisites.

This restores the ability, essentially lost in commit
ffaa44cb, 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
parent 86bc5218
...@@ -2394,13 +2394,25 @@ CopyFrom(CopyState cstate) ...@@ -2394,13 +2394,25 @@ CopyFrom(CopyState cstate)
/* /*
* Optimize if new relfilenode was created in this subxact or one of its * 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 * committed children and we won't see those rows later as part of an
* earlier scan or command. This ensures that if this subtransaction * 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 * aborts then the frozen rows won't be visible after xact cleanup. Note
* that the stronger test of exactly which subtransaction created it is * 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) 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()) if (!ThereAreNoPriorRegisteredSnapshots() || !ThereAreNoReadyPortals())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TRANSACTION_STATE), (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
......
...@@ -1645,6 +1645,14 @@ DeleteAllExportedSnapshotFiles(void) ...@@ -1645,6 +1645,14 @@ DeleteAllExportedSnapshotFiles(void)
FreeDir(s_dir); 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 bool
ThereAreNoPriorRegisteredSnapshots(void) ThereAreNoPriorRegisteredSnapshots(void)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment