Skip to content

Commit f9900df

Browse files
committed
Avoid spurious wait in concurrent reindex
This is like commit c98763b, but for REINDEX CONCURRENTLY. To wit: this flags indicates that the current process is safe to ignore for the purposes of waiting for other snapshots, when doing CREATE INDEX CONCURRENTLY and REINDEX CONCURRENTLY. This helps two processes doing either of those things not deadlock, and also avoids spurious waits. Author: Álvaro Herrera <alvherre@alvh.no-ip.org> Reviewed-by: Dmitry Dolgov <9erthalion6@gmail.com> Reviewed-by: Hamid Akhtar <hamid.akhtar@gmail.com> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Discussion: https://postgr.es/m/20201130195439.GA24598@alvherre.pgsql
1 parent 2ad78a8 commit f9900df

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

src/backend/commands/indexcmds.c

+47-1
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ CompareOpclassOptions(Datum *opts1, Datum *opts2, int natts)
385385
* lazy VACUUMs, because they won't be fazed by missing index entries
386386
* either. (Manual ANALYZEs, however, can't be excluded because they
387387
* might be within transactions that are going to do arbitrary operations
388-
* later.) Processes running CREATE INDEX CONCURRENTLY
388+
* later.) Processes running CREATE INDEX CONCURRENTLY or REINDEX CONCURRENTLY
389389
* on indexes that are neither expressional nor partial are also safe to
390390
* ignore, since we know that those processes won't examine any data
391391
* outside the table they're indexing.
@@ -3066,6 +3066,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
30663066
Oid indexId;
30673067
Oid tableId;
30683068
Oid amId;
3069+
bool safe; /* for set_indexsafe_procflags */
30693070
} ReindexIndexInfo;
30703071
List *heapRelationIds = NIL;
30713072
List *indexIds = NIL;
@@ -3377,6 +3378,9 @@ ReindexRelationConcurrently(Oid relationOid, int options)
33773378
heapRel = table_open(indexRel->rd_index->indrelid,
33783379
ShareUpdateExclusiveLock);
33793380

3381+
/* determine safety of this index for set_indexsafe_procflags */
3382+
idx->safe = (indexRel->rd_indexprs == NIL &&
3383+
indexRel->rd_indpred == NIL);
33803384
idx->tableId = RelationGetRelid(heapRel);
33813385
idx->amId = indexRel->rd_rel->relam;
33823386

@@ -3418,6 +3422,7 @@ ReindexRelationConcurrently(Oid relationOid, int options)
34183422

34193423
newidx = palloc(sizeof(ReindexIndexInfo));
34203424
newidx->indexId = newIndexId;
3425+
newidx->safe = idx->safe;
34213426
newidx->tableId = idx->tableId;
34223427
newidx->amId = idx->amId;
34233428

@@ -3485,6 +3490,11 @@ ReindexRelationConcurrently(Oid relationOid, int options)
34853490
CommitTransactionCommand();
34863491
StartTransactionCommand();
34873492

3493+
/*
3494+
* Because we don't take a snapshot in this transaction, there's no need
3495+
* to set the PROC_IN_SAFE_IC flag here.
3496+
*/
3497+
34883498
/*
34893499
* Phase 2 of REINDEX CONCURRENTLY
34903500
*
@@ -3514,6 +3524,10 @@ ReindexRelationConcurrently(Oid relationOid, int options)
35143524
*/
35153525
CHECK_FOR_INTERRUPTS();
35163526

3527+
/* Tell concurrent indexing to ignore us, if index qualifies */
3528+
if (newidx->safe)
3529+
set_indexsafe_procflags();
3530+
35173531
/* Set ActiveSnapshot since functions in the indexes may need it */
35183532
PushActiveSnapshot(GetTransactionSnapshot());
35193533

@@ -3534,8 +3548,14 @@ ReindexRelationConcurrently(Oid relationOid, int options)
35343548
PopActiveSnapshot();
35353549
CommitTransactionCommand();
35363550
}
3551+
35373552
StartTransactionCommand();
35383553

3554+
/*
3555+
* Because we don't take a snapshot or Xid in this transaction, there's no
3556+
* need to set the PROC_IN_SAFE_IC flag here.
3557+
*/
3558+
35393559
/*
35403560
* Phase 3 of REINDEX CONCURRENTLY
35413561
*
@@ -3564,6 +3584,10 @@ ReindexRelationConcurrently(Oid relationOid, int options)
35643584
*/
35653585
CHECK_FOR_INTERRUPTS();
35663586

3587+
/* Tell concurrent indexing to ignore us, if index qualifies */
3588+
if (newidx->safe)
3589+
set_indexsafe_procflags();
3590+
35673591
/*
35683592
* Take the "reference snapshot" that will be used by validate_index()
35693593
* to filter candidate tuples.
@@ -3607,6 +3631,9 @@ ReindexRelationConcurrently(Oid relationOid, int options)
36073631
* interesting tuples. But since it might not contain tuples deleted
36083632
* just before the reference snap was taken, we have to wait out any
36093633
* transactions that might have older snapshots.
3634+
*
3635+
* Because we don't take a snapshot or Xid in this transaction,
3636+
* there's no need to set the PROC_IN_SAFE_IC flag here.
36103637
*/
36113638
pgstat_progress_update_param(PROGRESS_CREATEIDX_PHASE,
36123639
PROGRESS_CREATEIDX_PHASE_WAIT_3);
@@ -3628,6 +3655,13 @@ ReindexRelationConcurrently(Oid relationOid, int options)
36283655

36293656
StartTransactionCommand();
36303657

3658+
/*
3659+
* Because this transaction only does catalog manipulations and doesn't do
3660+
* any index operations, we can set the PROC_IN_SAFE_IC flag here
3661+
* unconditionally.
3662+
*/
3663+
set_indexsafe_procflags();
3664+
36313665
forboth(lc, indexIds, lc2, newIndexIds)
36323666
{
36333667
ReindexIndexInfo *oldidx = lfirst(lc);
@@ -3675,6 +3709,12 @@ ReindexRelationConcurrently(Oid relationOid, int options)
36753709
CommitTransactionCommand();
36763710
StartTransactionCommand();
36773711

3712+
/*
3713+
* While we could set PROC_IN_SAFE_IC if all indexes qualified, there's no
3714+
* real need for that, because we only acquire an Xid after the wait is
3715+
* done, and that lasts for a very short period.
3716+
*/
3717+
36783718
/*
36793719
* Phase 5 of REINDEX CONCURRENTLY
36803720
*
@@ -3705,6 +3745,12 @@ ReindexRelationConcurrently(Oid relationOid, int options)
37053745
CommitTransactionCommand();
37063746
StartTransactionCommand();
37073747

3748+
/*
3749+
* While we could set PROC_IN_SAFE_IC if all indexes qualified, there's no
3750+
* real need for that, because we only acquire an Xid after the wait is
3751+
* done, and that lasts for a very short period.
3752+
*/
3753+
37083754
/*
37093755
* Phase 6 of REINDEX CONCURRENTLY
37103756
*

src/include/storage/proc.h

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct XidCache
5454
#define PROC_IS_AUTOVACUUM 0x01 /* is it an autovac worker? */
5555
#define PROC_IN_VACUUM 0x02 /* currently running lazy vacuum */
5656
#define PROC_IN_SAFE_IC 0x04 /* currently running CREATE INDEX
57+
* CONCURRENTLY or REINDEX
5758
* CONCURRENTLY on non-expressional,
5859
* non-partial index */
5960
#define PROC_VACUUM_FOR_WRAPAROUND 0x08 /* set by autovac only */

0 commit comments

Comments
 (0)