diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 5848305a3518b4139211088d7223b4758aeb0946..4fe7d4012f042cf7192582c61ffee3be9bd429d9 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -319,6 +319,7 @@ DefineIndex(IndexStmt *stmt, int16 *coloptions; IndexInfo *indexInfo; int numberOfAttributes; + TransactionId limitXmin; VirtualTransactionId *old_lockholders; VirtualTransactionId *old_snapshots; int n_old_snapshots; @@ -769,6 +770,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 @@ -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. */