mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
ALTER TABLE ... DETACH PARTITION ... CONCURRENTLY
Allow a partition be detached from its partitioned table without blocking concurrent queries, by running in two transactions and only requiring ShareUpdateExclusive in the partitioned table. Because it runs in two transactions, it cannot be used in a transaction block. This is the main reason to use dedicated syntax: so that users can choose to use the original mode if they need it. But also, it doesn't work when a default partition exists (because an exclusive lock would still need to be obtained on it, in order to change its partition constraint.) In case the second transaction is cancelled or a crash occurs, there's ALTER TABLE .. DETACH PARTITION .. FINALIZE, which executes the final steps. The main trick to make this work is the addition of column pg_inherits.inhdetachpending, initially false; can only be set true in the first part of this command. Once that is committed, concurrent transactions that use a PartitionDirectory will include or ignore partitions so marked: in optimizer they are ignored if the row is marked committed for the snapshot; in executor they are always included. As a result, and because of the way PartitionDirectory caches partition descriptors, queries that were planned before the detach will see the rows in the detached partition and queries that are planned after the detach, won't. A CHECK constraint is created that duplicates the partition constraint. This is probably not strictly necessary, and some users will prefer to remove it afterwards, but if the partition is re-attached to a partitioned table, the constraint needn't be rechecked. Author: Álvaro Herrera <alvherre@alvh.no-ip.org> Reviewed-by: Amit Langote <amitlangote09@gmail.com> Reviewed-by: Justin Pryzby <pryzby@telsasoft.com> Discussion: https://postgr.es/m/20200803234854.GA24158@alvherre.pgsql
This commit is contained in:
@ -4497,6 +4497,16 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l
|
||||
when using declarative partitioning.
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="catalog_table_entry"><para role="column_definition">
|
||||
<structfield>inhdetachpending</structfield> <type>bool</type>
|
||||
</para>
|
||||
<para>
|
||||
<literal>true</literal> for a partition that is in the process of
|
||||
being detached; <literal>false</literal> otherwise.
|
||||
</para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
@ -36,7 +36,7 @@ ALTER TABLE ALL IN TABLESPACE <replaceable class="parameter">name</replaceable>
|
||||
ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
|
||||
ATTACH PARTITION <replaceable class="parameter">partition_name</replaceable> { FOR VALUES <replaceable class="parameter">partition_bound_spec</replaceable> | DEFAULT }
|
||||
ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
|
||||
DETACH PARTITION <replaceable class="parameter">partition_name</replaceable>
|
||||
DETACH PARTITION <replaceable class="parameter">partition_name</replaceable> [ CONCURRENTLY | FINALIZE ]
|
||||
|
||||
<phrase>where <replaceable class="parameter">action</replaceable> is one of:</phrase>
|
||||
|
||||
@ -954,7 +954,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>DETACH PARTITION</literal> <replaceable class="parameter">partition_name</replaceable></term>
|
||||
<term><literal>DETACH PARTITION <replaceable class="parameter">partition_name</replaceable> [ CONCURRENTLY | FINALIZE ]</literal></term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
This form detaches the specified partition of the target table. The detached
|
||||
@ -965,6 +966,27 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
|
||||
<literal>SHARE</literal> lock is obtained on any tables that reference
|
||||
this partitioned table in foreign key constraints.
|
||||
</para>
|
||||
<para>
|
||||
If <literal>CONCURRENTLY</literal> is specified, it runs using a reduced
|
||||
lock level to avoid blocking other sessions that might be accessing the
|
||||
partitioned table. In this mode, two transactions are used internally.
|
||||
During the first transaction, a <literal>SHARE UPDATE EXCLUSIVE</literal>
|
||||
lock is taken on both parent table and partition, and the partition is
|
||||
marked as undergoing detach; at that point, the transaction is committed
|
||||
and all other transactions using the partitioned table are waited for.
|
||||
Once all those transactions have completed, the second transaction
|
||||
acquires <literal>SHARE UPDATE EXCLUSIVE</literal> on the partitioned
|
||||
table and <literal>ACCESS EXCLUSIVE</literal> on the partition,
|
||||
and the detach process completes. A <literal>CHECK</literal> constraint
|
||||
that duplicates the partition constraint is added to the partition.
|
||||
<literal>CONCURRENTLY</literal> cannot be run in a transaction block and
|
||||
is not allowed if the partitioned table contains a default partition.
|
||||
</para>
|
||||
<para>
|
||||
If <literal>FINALIZE</literal> is specified, a previous
|
||||
<literal>DETACH CONCURRENTLY</literal> invocation that was cancelled or
|
||||
interrupted is completed.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
Reference in New Issue
Block a user