aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 f855befd4d4..66eae92a4c1 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -320,6 +320,7 @@ DefineIndex(IndexStmt *stmt,
int16 *coloptions;
IndexInfo *indexInfo;
int numberOfAttributes;
+ TransactionId limitXmin;
VirtualTransactionId *old_lockholders;
VirtualTransactionId *old_snapshots;
int n_old_snapshots;
@@ -770,6 +771,18 @@ DefineIndex(IndexStmt *stmt,
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
@@ -801,7 +814,7 @@ DefineIndex(IndexStmt *stmt,
* 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);
@@ -818,7 +831,7 @@ DefineIndex(IndexStmt *stmt,
int j;
int k;
- newer_snapshots = GetCurrentVirtualXIDs(snapshot->xmin,
+ newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
true, false,
PROC_IS_AUTOVACUUM | PROC_IN_VACUUM,
&n_newer_snapshots);
@@ -857,12 +870,6 @@ DefineIndex(IndexStmt *stmt,
*/
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.
*/