Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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 <andres@anarazel.de> Reviewed-by: Andres Freund <andres@anarazel.de> Reviewed-by: Michael Paquier <michael@paquier.xyz> 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

+33-12
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)