Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit add85ea

Browse files
committed
Fix table lock levels for REINDEX INDEX CONCURRENTLY
REINDEX CONCURRENTLY locks tables with ShareUpdateExclusiveLock rather than the ShareLock used by a plain REINDEX. However, RangeVarCallbackForReindexIndex() was not updated for that and still used the ShareLock only. This would lead to lock upgrades later, leading to possible deadlocks. Reported-by: Andres Freund <[email protected]> Reviewed-by: Andres Freund <[email protected]> Reviewed-by: Michael Paquier <[email protected]> Discussion: https://www.postgresql.org/message-id/flat/20190430151735.wi52sxjvxsjvaxxt%40alap3.anarazel.de
1 parent 8efe710 commit add85ea

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

src/backend/commands/indexcmds.c

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ static bool ReindexRelationConcurrently(Oid relationOid, int options);
9191
static void ReindexPartitionedIndex(Relation parentIdx);
9292
static void update_relispartition(Oid relationId, bool newval);
9393

94+
/*
95+
* callback argument type for RangeVarCallbackForReindexIndex()
96+
*/
97+
struct ReindexIndexCallbackState
98+
{
99+
bool concurrent; /* flag from statement */
100+
Oid locked_table_oid; /* tracks previously locked table */
101+
};
102+
94103
/*
95104
* CheckIndexCompatible
96105
* Determine whether an existing index definition is compatible with a
@@ -2303,8 +2312,8 @@ ChooseIndexColumnNames(List *indexElems)
23032312
void
23042313
ReindexIndex(RangeVar *indexRelation, int options, bool concurrent)
23052314
{
2315+
struct ReindexIndexCallbackState state;
23062316
Oid indOid;
2307-
Oid heapOid = InvalidOid;
23082317
Relation irel;
23092318
char persistence;
23102319

@@ -2313,11 +2322,13 @@ ReindexIndex(RangeVar *indexRelation, int options, bool concurrent)
23132322
* obtain lock on table first, to avoid deadlock hazard. The lock level
23142323
* used here must match the index lock obtained in reindex_index().
23152324
*/
2325+
state.concurrent = concurrent;
2326+
state.locked_table_oid = InvalidOid;
23162327
indOid = RangeVarGetRelidExtended(indexRelation,
23172328
concurrent ? ShareUpdateExclusiveLock : AccessExclusiveLock,
23182329
0,
23192330
RangeVarCallbackForReindexIndex,
2320-
(void *) &heapOid);
2331+
&state);
23212332

23222333
/*
23232334
* Obtain the current persistence of the existing index. We already hold
@@ -2350,7 +2361,15 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
23502361
Oid relId, Oid oldRelId, void *arg)
23512362
{
23522363
char relkind;
2353-
Oid *heapOid = (Oid *) arg;
2364+
struct ReindexIndexCallbackState *state = arg;
2365+
LOCKMODE table_lockmode;
2366+
2367+
/*
2368+
* Lock level here should match table lock in reindex_index() for
2369+
* non-concurrent case and table locks used by index_concurrently_*() for
2370+
* concurrent case.
2371+
*/
2372+
table_lockmode = state->concurrent ? ShareUpdateExclusiveLock : ShareLock;
23542373

23552374
/*
23562375
* If we previously locked some other index's heap, and the name we're
@@ -2359,9 +2378,8 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
23592378
*/
23602379
if (relId != oldRelId && OidIsValid(oldRelId))
23612380
{
2362-
/* lock level here should match reindex_index() heap lock */
2363-
UnlockRelationOid(*heapOid, ShareLock);
2364-
*heapOid = InvalidOid;
2381+
UnlockRelationOid(state->locked_table_oid, table_lockmode);
2382+
state->locked_table_oid = InvalidOid;
23652383
}
23662384

23672385
/* If the relation does not exist, there's nothing more to do. */
@@ -2389,14 +2407,17 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
23892407
/* Lock heap before index to avoid deadlock. */
23902408
if (relId != oldRelId)
23912409
{
2410+
Oid table_oid = IndexGetRelation(relId, true);
2411+
23922412
/*
2393-
* Lock level here should match reindex_index() heap lock. If the OID
2394-
* isn't valid, it means the index as concurrently dropped, which is
2395-
* not a problem for us; just return normally.
2413+
* If the OID isn't valid, it means the index was concurrently
2414+
* dropped, which is not a problem for us; just return normally.
23962415
*/
2397-
*heapOid = IndexGetRelation(relId, true);
2398-
if (OidIsValid(*heapOid))
2399-
LockRelationOid(*heapOid, ShareLock);
2416+
if (OidIsValid(table_oid))
2417+
{
2418+
LockRelationOid(table_oid, table_lockmode);
2419+
state->locked_table_oid = table_oid;
2420+
}
24002421
}
24012422
}
24022423

0 commit comments

Comments
 (0)