aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/indexcmds.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index a08ad1324ba..34153f5eb9a 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -142,6 +142,7 @@ DefineIndex(RangeVar *heapRelation,
int16 *coloptions;
IndexInfo *indexInfo;
int numberOfAttributes;
+ TransactionId limitXmin;
VirtualTransactionId *old_lockholders;
VirtualTransactionId *old_snapshots;
int n_old_snapshots;
@@ -577,6 +578,18 @@ DefineIndex(RangeVar *heapRelation,
validate_index(relationId, indexRelationId, snapshot);
/*
+ * Drop the reference snapshot. We must do this before waiting out other
+ * snapshot holders, else we will deadlock against other processes also
+ * doing CREATE INDEX CONCURRENTLY, which would see our snapshot as one
+ * they must wait for. But first, save the snapshot's xmin to use as
+ * limitXmin for GetCurrentVirtualXIDs().
+ */
+ limitXmin = snapshot->xmin;
+
+ PopActiveSnapshot();
+ UnregisterSnapshot(snapshot);
+
+ /*
* The index is now valid in the sense that it contains all currently
* interesting tuples. But since it might not contain tuples deleted just
* before the reference snap was taken, we have to wait out any
@@ -608,7 +621,7 @@ DefineIndex(RangeVar *heapRelation,
* GetCurrentVirtualXIDs. If, during any iteration, a particular vxid
* doesn't show up in the output, we know we can forget about it.
*/
- old_snapshots = GetCurrentVirtualXIDs(snapshot->xmin, true, false,
+ old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
PROC_IS_AUTOVACUUM | PROC_IN_VACUUM,
&n_old_snapshots);
@@ -625,7 +638,7 @@ DefineIndex(RangeVar *heapRelation,
int j;
int k;
- newer_snapshots = GetCurrentVirtualXIDs(snapshot->xmin,
+ newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
true, false,
PROC_IS_AUTOVACUUM | PROC_IN_VACUUM,
&n_newer_snapshots);
@@ -664,12 +677,6 @@ DefineIndex(RangeVar *heapRelation,
*/
CacheInvalidateRelcacheByRelid(heaprelid.relId);
- /* we can now do away with our active snapshot */
- PopActiveSnapshot();
-
- /* And we can remove the validating snapshot too */
- UnregisterSnapshot(snapshot);
-
/*
* Last thing to do is release the session-level lock on the parent table.
*/