Change lock level for renaming index (either ALTER INDEX or implicitly
via some other commands) from AccessExclusiveLock to ShareUpdateExclusiveLock.
One reason we need a strong lock for relation renaming is that the name change causes a rebuild of the relcache entry. Concurrent sessions that have the relation open might not be able to handle the relcache entry changing underneath them. Therefore, we need to lock the relation in a way that no one can have the relation open concurrently. But for indexes, the relcache handles reloads specially in RelationReloadIndexInfo() in a way that keeps changes in the relcache entry to a minimum. As long as no one keeps pointers to rd_amcache and rd_options around across possible relcache flushes, which is the case, this ought to be safe.
We also want to use a self-exclusive lock for correctness, so that concurrent DDL doesn't overwrite the rename if they start updating while still seeing the old version. Therefore, we use ShareUpdateExclusiveLock, which is already used by other DDL commands that want to operate in a concurrent manner.
The reason this is interesting at all is that renaming an index is a typical part of a concurrent reindexing workflow (CREATE INDEX CONCURRENTLY new + DROP INDEX CONCURRENTLY old + rename back). And indeed a future built-in REINDEX CONCURRENTLY might rely on the ability to do concurrent renames as well.
1b5d797cd4 Lower lock level for renaming indexes
doc/src/sgml/mvcc.sgml | 12 ++++++------
doc/src/sgml/ref/alter_index.sgml | 9 ++++++++-
src/backend/commands/cluster.c | 4 ++--
src/backend/commands/tablecmds.c | 27 +++++++++++++++++----------
src/backend/commands/typecmds.c | 2 +-
src/include/commands/tablecmds.h | 3 ++-
6 files changed, 36 insertions(+), 21 deletions(-)