为什么 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 上的所有并发事务都完成。
这是使用 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 上的所有并发事务都完成。