aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/spgist/spgvacuum.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/spgist/spgvacuum.c')
-rw-r--r--src/backend/access/spgist/spgvacuum.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index 8a5b540c809..85bc02b92c8 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -189,7 +189,9 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer,
/*
* Add target TID to pending list if the redirection could have
- * happened since VACUUM started.
+ * happened since VACUUM started. (If xid is invalid, assume it
+ * must have happened before VACUUM started, since REINDEX
+ * CONCURRENTLY locks out VACUUM.)
*
* Note: we could make a tighter test by seeing if the xid is
* "running" according to the active snapshot; but snapmgr.c
@@ -524,8 +526,17 @@ vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer)
dt = (SpGistDeadTuple) PageGetItem(page, PageGetItemId(page, i));
+ /*
+ * We can convert a REDIRECT to a PLACEHOLDER if there could no longer
+ * be any index scans "in flight" to it. Such an index scan would
+ * have to be in a transaction whose snapshot sees the REDIRECT's XID
+ * as still running, so comparing the XID against global xmin is a
+ * conservatively safe test. If the XID is invalid, it must have been
+ * inserted by REINDEX CONCURRENTLY, so we can zap it immediately.
+ */
if (dt->tupstate == SPGIST_REDIRECT &&
- GlobalVisTestIsRemovableXid(vistest, dt->xid))
+ (!TransactionIdIsValid(dt->xid) ||
+ GlobalVisTestIsRemovableXid(vistest, dt->xid)))
{
dt->tupstate = SPGIST_PLACEHOLDER;
Assert(opaque->nRedirection > 0);