这是使用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
上的锁定。但是,我完全不清楚为什么甚至需要锁定。
感谢您的所有想法!
答案 0 :(得分:2)
这与分区无关。
外键在PostgreSQL中实现为触发器,当你删除分区时,必须删除实现(一半)外键的bars
上的触发器。
现在删除触发器需要在表上锁定ACCESS EXCLUSIVE
,并且阻塞直到表上的所有并发事务都完成。