Почему секционированные таблицы в PostgreSQL при удалении блокируют другие таблицы? - PullRequest
0 голосов
/ 08 июня 2018

Это использует 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 голосов
/ 09 июня 2018

Это не имеет ничего общего с секционированием.

Внешние ключи реализованы как триггеры в PostgreSQL, и когда вы отбрасываете раздел, триггер на bars, который реализует (одну половину) внешний ключ, имеетчтобы быть отброшенным.

Теперь для сброса триггера требуется блокировка ACCESS EXCLUSIVE для таблицы, которая блокирует до тех пор, пока не завершатся все параллельные транзакции в таблице.

...