为什么 PostgreSQL 中的分区表在删除时会锁定其他表?

Why do partitioned tables in PostgreSQL take locks on other tables when being dropped?

这是使用 PostgreSQL 10.4

我有一个分区 table 设置为:

                            Table "public.foo_partitioned"
   Column        |            Type             | Collation | Nullable |    Default
---------------------+-----------------------------+-----------+----------+----------------
 bar_id             | integer                     |           | not null |
 ...
Partition key: LIST (bar_id)
Number of partitions: 10 (Use \d+ to list them.)

bar_id 上有一个引用 table 条柱的外键。

当我尝试删除分区 foo_partitioned_1 时,如果 bars 上存在未完成的空闲事务查询,则删除会阻止。这对我来说似乎很奇怪,针对单独的 table 的查询不允许删除此分区。我尝试先分离分区,但这也不起作用。我可以查询锁 tables 并获取如下信息:

  pid  |   usename   | blocked_by |       blocked_query
-------+-------------+------------+----------------------------
 59897 | my_user | {59888}    | DROP TABLE foo_partitioned_1

当我运行以下

select pgl.*, relname from pg_locks pgl join pg_class pgt on pgl.relation=pgt.oid  where pid=59897;

我得到:

 locktype | database | relation |...| virtualtransaction |  pid  |        mode         | granted | fastpath |                 relname
----------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+-------+---------------------+---------+----------+-----------------------------------------
 relation |    16401 |     2620 |...| 7/758              | 60266 | RowExclusiveLock    | t       | t        | pg_trigger
 relation |    16401 |     2608 |...| 7/758              | 60266 | RowExclusiveLock    | t       | t        | pg_depend
 relation |    16401 |   940755 |...| 7/758              | 60266 | AccessExclusiveLock | t       | f        | foo_partitioned
 relation |    16401 |   941051 |...| 7/758              | 60266 | AccessExclusiveLock | t       | f        | uq_foo_partitioned_1
 relation |    16401 |   742405 |...| 7/758              | 60266 | AccessExclusiveLock | f       | f        | bars
 relation |    16401 |     2702 |...| 7/758              | 60266 | AccessShareLock     | t       | f        | pg_trigger_oid_index
 relation |    16401 |   941047 |...| 7/758              | 60266 | AccessShareLock     | t       | f        | foo_partitioned_1
 relation |    16401 |   941047 |...| 7/758              | 60266 | AccessExclusiveLock | t       | f        | foo_partitioned_1

唯一未授予查询的锁是 bars 上的锁。但是,我完全不清楚为什么需要这个锁。

感谢所有的想法!

这与分区无关。

外键在 PostgreSQL 中作为触发器实现,当您删除分区时,必须删除 bars 上实现(一半)外键的触发器。

现在删除触发器需要 table 上的 ACCESS EXCLUSIVE 锁,并且会阻塞,直到 table 上的所有并发事务都完成。