Удаление секции без эксклюзивной блокировки на родительскую таблицу
Актуально для СУБД Pangolin версии 6.1.0 и выше в связи с добавлением доработки ALTER TABLE ... DETACH PARTITION ... CONCURRENTLY
ядра PostgreSQL 14 версии.
Раздел содержит способ инициализации отсоединения секции без потери доступа к самой таблице с помощью конструкции DETACH PARTITION ... CONCURRENTLY
.
Ручное секционирование
Тест 1. Выполнение команды SELECT при отсоединении секции
-
Создайте таблицы, секции, данные:
DROP TABLE IF EXISTS test_TABLE_mnl_part;
CREATE TABLE test_TABLE_mnl_part
(
id bigint,
someint bigint,
txt text,
isThat bool
) PARTITION BY RANGE (someint);
do $$
DECLARE
n_from int = 1;
n_to int = 100000;
BEGIN
FOR i IN 1..100 loop
EXECUTE
'CREATE TABLE test_table_mnl_part' || i || ' PARTITION OF test_table_mnl_part
FOR VALUES FROM (' || n_from || ') TO (' || n_to || ');';
n_from = n_to;
n_to = n_from + 100000;
END LOOP;
END;
$$;
INSERT INTO test_table_mnl_part(id, someint, txt, isThat)
SELECT x, x, md5((random() * 10)::text), false FROM generate_series(1,9999999) AS x; -
Подготовьте три терминала (
t1
,t2
,t3
), в каждом из которых будут выполняться команды из тестов.-
Терминал
t1
. Открытие транзакции и обращение к таблице:BEGIN;
SELECT count(*) FROM test_table_mnl_part; -
Терминал
t2
. Отсоединение секции в режиме concurrently:ALTER TABLE test_table_mnl_part DETACH PARTITION test_table_mnl_part10 concurrently;
Заметьте, что при выполнении команды
ALTER TABLE
произошло зависание, транзакция не завершится, покаt1
не будет завершена («закомичена»). Тем не менее, в таблице блокировок можно убедиться, что блоки ровок на отношение (relation
) нет, но есть наvirtualxid
.А сама секция отмечена как
DETACH PENDING
(\d+ test_table_mnl_part
):...
test_table_mnl_part10 FOR VALUES FROM ('900000') TO ('1000000') (DETACH PENDING),
...
*/ -
Терминал
t3
:Проверка блокировок с помощью таблицы
pg_locks
:SELECT pl.locktype, pl.relation, pl.virtualxid, pl.transactionid, pl.pid, pl.mode, psa.query
FROM pg_locks AS pl
LEFT JOIN pg_stat_activity AS psa ON pl.pid = psa.pid
ORDER BY psa.query;
/*
locktype | relation | virtualxid | transactionid | pid | mode | query
------------+----------+------------+---------------+---------+-----------------+-----------------------------------------------------------------------------------------------
virtualxid | | 16/18 | | 3149851 | ShareLock | ALTER TABLE test_table_mnl_part DETACH PARTITION test_table_mnl_part10 concurrently;
virtualxid | | 14/19 | | 3149851 | ExclusiveLock | ALTER TABLE test_table_mnl_part DETACH PARTITION test_table_mnl_part10 concurrently;
relation | 19340 | | | 3149849 | AccessShareLock | SELECT count(*) FROM test_table_mnl_part;
relation | 19335 | | | 3149849 | AccessShareLock | SELECT count(*) FROM test_table_mnl_part;
...
*/Запрос количества строк у таблицы:
SELECT count(*) FROM test_table_mnl_part;
/*
count
---------
9899999
(1 row)
*/
-