aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/mvcc.sgml12
-rw-r--r--doc/src/sgml/ref/alter_index.sgml9
-rw-r--r--src/backend/commands/cluster.c4
-rw-r--r--src/backend/commands/tablecmds.c27
-rw-r--r--src/backend/commands/typecmds.c2
-rw-r--r--src/include/commands/tablecmds.h3
6 files changed, 36 insertions, 21 deletions
diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml
index 73934e5cf37..bedd9a008d3 100644
--- a/doc/src/sgml/mvcc.sgml
+++ b/doc/src/sgml/mvcc.sgml
@@ -926,10 +926,10 @@ ERROR: could not serialize access due to read/write dependencies among transact
<para>
Acquired by <command>VACUUM</command> (without <option>FULL</option>),
<command>ANALYZE</command>, <command>CREATE INDEX CONCURRENTLY</command>,
- <command>CREATE STATISTICS</command> and
- <command>ALTER TABLE VALIDATE</command> and other
- <command>ALTER TABLE</command> variants (for full details see
- <xref linkend="sql-altertable"/>).
+ <command>CREATE STATISTICS</command>, and certain <command>ALTER
+ INDEX</command> and <command>ALTER TABLE</command> variants (for full
+ details see <xref linkend="sql-alterindex"/> and <xref
+ linkend="sql-altertable"/>).
</para>
</listitem>
</varlistentry>
@@ -970,7 +970,7 @@ ERROR: could not serialize access due to read/write dependencies among transact
</para>
<para>
- Acquired by <command>CREATE TRIGGER</command> and many forms of
+ Acquired by <command>CREATE TRIGGER</command> and some forms of
<command>ALTER TABLE</command> (see <xref linkend="sql-altertable"/>).
</para>
</listitem>
@@ -1020,7 +1020,7 @@ ERROR: could not serialize access due to read/write dependencies among transact
<command>CLUSTER</command>, <command>VACUUM FULL</command>,
and <command>REFRESH MATERIALIZED VIEW</command> (without
<option>CONCURRENTLY</option>)
- commands. Many forms of <command>ALTER TABLE</command> also acquire
+ commands. Many forms of <command>ALTER INDEX</command> and <command>ALTER TABLE</command> also acquire
a lock at this level. This is also the default lock mode for
<command>LOCK TABLE</command> statements that do not specify
a mode explicitly.
diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml
index d0a62123583..6d34dbb74e5 100644
--- a/doc/src/sgml/ref/alter_index.sgml
+++ b/doc/src/sgml/ref/alter_index.sgml
@@ -39,7 +39,10 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="parameter">name</replaceable>
<para>
<command>ALTER INDEX</command> changes the definition of an existing index.
- There are several subforms:
+ There are several subforms described below. Note that the lock level required
+ may differ for each subform. An <literal>ACCESS EXCLUSIVE</literal> lock is held
+ unless explicitly noted. When multiple subcommands are listed, the lock
+ held will be the strictest one required from any subcommand.
<variablelist>
@@ -53,6 +56,10 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="parameter">name</replaceable>
or <literal>EXCLUDE</literal>), the constraint is renamed as well.
There is no effect on the stored data.
</para>
+ <para>
+ Renaming an index acquires a <literal>SHARE UPDATE EXCLUSIVE</literal>
+ lock.
+ </para>
</listitem>
</varlistentry>
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 68be4709771..5ecd2565b4d 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1661,14 +1661,14 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u",
OIDOldHeap);
RenameRelationInternal(newrel->rd_rel->reltoastrelid,
- NewToastName, true);
+ NewToastName, true, false);
/* ... and its valid index too. */
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
OIDOldHeap);
RenameRelationInternal(toastidx,
- NewToastName, true);
+ NewToastName, true, true);
}
relation_close(newrel, NoLock);
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 946119fa860..73da6c39c22 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -3044,7 +3044,7 @@ rename_constraint_internal(Oid myrelid,
|| con->contype == CONSTRAINT_UNIQUE
|| con->contype == CONSTRAINT_EXCLUSION))
/* rename the index; this renames the constraint as well */
- RenameRelationInternal(con->conindid, newconname, false);
+ RenameRelationInternal(con->conindid, newconname, false, true);
else
RenameConstraintById(constraintOid, newconname);
@@ -3112,6 +3112,7 @@ RenameConstraint(RenameStmt *stmt)
ObjectAddress
RenameRelation(RenameStmt *stmt)
{
+ bool is_index = stmt->renameType == OBJECT_INDEX;
Oid relid;
ObjectAddress address;
@@ -3123,7 +3124,8 @@ RenameRelation(RenameStmt *stmt)
* Lock level used here should match RenameRelationInternal, to avoid lock
* escalation.
*/
- relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
+ relid = RangeVarGetRelidExtended(stmt->relation,
+ is_index ? ShareUpdateExclusiveLock : AccessExclusiveLock,
stmt->missing_ok ? RVR_MISSING_OK : 0,
RangeVarCallbackForAlterRelation,
(void *) stmt);
@@ -3137,7 +3139,7 @@ RenameRelation(RenameStmt *stmt)
}
/* Do the work */
- RenameRelationInternal(relid, stmt->newname, false);
+ RenameRelationInternal(relid, stmt->newname, false, is_index);
ObjectAddressSet(address, RelationRelationId, relid);
@@ -3148,7 +3150,7 @@ RenameRelation(RenameStmt *stmt)
* RenameRelationInternal - change the name of a relation
*/
void
-RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
+RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bool is_index)
{
Relation targetrelation;
Relation relrelation; /* for RELATION relation */
@@ -3157,11 +3159,16 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Oid namespaceId;
/*
- * Grab an exclusive lock on the target table, index, sequence, view,
- * materialized view, or foreign table, which we will NOT release until
- * end of transaction.
+ * Grab a lock on the target relation, which we will NOT release until end
+ * of transaction. We need at least a self-exclusive lock so that
+ * concurrent DDL doesn't overwrite the rename if they start updating
+ * while still seeing the old version. The lock also guards against
+ * triggering relcache reloads in concurrent sessions, which might not
+ * handle this information changing under them. For indexes, we can use a
+ * reduced lock level because RelationReloadIndexInfo() handles indexes
+ * specially.
*/
- targetrelation = relation_open(myrelid, AccessExclusiveLock);
+ targetrelation = relation_open(myrelid, is_index ? ShareUpdateExclusiveLock : AccessExclusiveLock);
namespaceId = RelationGetNamespace(targetrelation);
/*
@@ -3214,7 +3221,7 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
}
/*
- * Close rel, but keep exclusive lock!
+ * Close rel, but keep lock!
*/
relation_close(targetrelation, NoLock);
}
@@ -7076,7 +7083,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
ereport(NOTICE,
(errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"",
indexName, constraintName)));
- RenameRelationInternal(index_oid, constraintName, false);
+ RenameRelationInternal(index_oid, constraintName, false, true);
}
/* Extra checks needed if making primary key */
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 66f7c577267..285a0be6436 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3255,7 +3255,7 @@ RenameType(RenameStmt *stmt)
* RenameRelationInternal will call RenameTypeInternal automatically.
*/
if (typTup->typtype == TYPTYPE_COMPOSITE)
- RenameRelationInternal(typTup->typrelid, newTypeName, false);
+ RenameRelationInternal(typTup->typrelid, newTypeName, false, false);
else
RenameTypeInternal(typeOid, newTypeName,
typTup->typnamespace);
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 138de84e832..2afcd5be442 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -67,7 +67,8 @@ extern ObjectAddress RenameConstraint(RenameStmt *stmt);
extern ObjectAddress RenameRelation(RenameStmt *stmt);
extern void RenameRelationInternal(Oid myrelid,
- const char *newrelname, bool is_internal);
+ const char *newrelname, bool is_internal,
+ bool is_index);
extern void find_composite_type_dependencies(Oid typeOid,
Relation origRelation,