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

时间:2018-06-08 20:14:14

标签: postgresql partitioning postgresql-10

这是使用PostgreSQL 10.4

我将分区表设置为:

                            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上有一个引用表栏的外键。

当我尝试删除分区foo_partitioned_1时,如果bars上存在未完成的空闲事务查询,则删除阻塞。这对我来说似乎很奇怪,对于一个单独的表进行查询时,不允许对此分区进行删除。我尝试首先分离分区,这也是行不通的。我可以查询锁定表并获取如下信息:

  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上的锁定。但是,我完全不清楚为什么甚至需要锁定。

感谢您的所有想法!

1 个答案:

答案 0 :(得分:2)

这与分区无关。

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

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