Fallout from changing index locking rules: we can reduce the strength

of locking used by REINDEX.  REINDEX needs only ShareLock on the parent
table, same as CREATE INDEX, plus an exclusive lock on the specific index
being processed.
This commit is contained in:
Tom Lane 2004-10-01 17:11:50 +00:00
parent 4c5e810fcd
commit b1f8a37aa7
2 changed files with 23 additions and 24 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.239 2004/08/31 17:10:36 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.240 2004/10/01 17:11:49 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -777,7 +777,7 @@ index_drop(Oid indexId)
* backend might be in the midst of devising a query plan that will * backend might be in the midst of devising a query plan that will
* use the index. The parser and planner take care to hold an * use the index. The parser and planner take care to hold an
* appropriate lock on the parent table while working, but having them * appropriate lock on the parent table while working, but having them
* hold locks on all the indexes too seems overly complex. We do grab * hold locks on all the indexes too seems overly expensive. We do grab
* exclusive lock on the index too, just to be safe. Both locks must * exclusive lock on the index too, just to be safe. Both locks must
* be held till end of transaction, else other backends will still see * be held till end of transaction, else other backends will still see
* this index in pg_index. * this index in pg_index.
@ -1655,26 +1655,19 @@ reindex_index(Oid indexId)
bool inplace; bool inplace;
/* /*
* Open our index relation and get an exclusive lock on it. * Open and lock the parent heap relation. ShareLock is sufficient
* * since we only need to be sure no schema or data changes are going on.
* Note: for REINDEX INDEX, doing this before opening the parent heap */
* relation means there's a possibility for deadlock failure against heapId = IndexGetRelation(indexId);
* another xact that is doing normal accesses to the heap and index. heapRelation = heap_open(heapId, ShareLock);
* However, it's not real clear why you'd be wanting to do REINDEX
* INDEX on a table that's in active use, so I'd rather have the /*
* protection of making sure the index is locked down. In the REINDEX * Open the target index relation and get an exclusive lock on it,
* TABLE and REINDEX DATABASE cases, there is no problem because * to ensure that no one else is touching this particular index.
* caller already holds exclusive lock on the parent table.
*/ */
iRel = index_open(indexId); iRel = index_open(indexId);
LockRelation(iRel, AccessExclusiveLock); LockRelation(iRel, AccessExclusiveLock);
/* Get OID of index's parent table */
heapId = iRel->rd_index->indrelid;
/* Open and lock the parent heap relation */
heapRelation = heap_open(heapId, AccessExclusiveLock);
/* /*
* If it's a shared index, we must do inplace processing (because we * If it's a shared index, we must do inplace processing (because we
* have no way to update relfilenode in other databases). Otherwise * have no way to update relfilenode in other databases). Otherwise
@ -1759,11 +1752,10 @@ reindex_relation(Oid relid, bool toast_too)
ListCell *indexId; ListCell *indexId;
/* /*
* Ensure to hold an exclusive lock throughout the transaction. The * Open and lock the relation. ShareLock is sufficient since we only
* lock could perhaps be less intensive (in the non-overwrite case) * need to prevent schema and data changes in it.
* but for now it's AccessExclusiveLock for simplicity.
*/ */
rel = heap_open(relid, AccessExclusiveLock); rel = heap_open(relid, ShareLock);
toast_relid = rel->rd_rel->reltoastrelid; toast_relid = rel->rd_rel->reltoastrelid;

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.96 2004/08/29 05:06:44 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.97 2004/10/01 17:11:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -90,7 +90,14 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
int i; int i;
int16 amorderstrategy; int16 amorderstrategy;
/* Extract info from the relation descriptor for the index */ /*
* Extract info from the relation descriptor for the index.
*
* Note that we take no lock on the index; we assume our lock on
* the parent table will protect the index's schema information.
* When and if the executor actually uses the index, it will take
* a lock as needed to protect the access to the index contents.
*/
indexRelation = index_open(indexoid); indexRelation = index_open(indexoid);
index = indexRelation->rd_index; index = indexRelation->rd_index;