Я довольно новичок в разработке баз данных и PostgreSQL в целом, но мне известна общая концепция управления версиями строк, транзакций и эксклюзивных блокировок в Postgres (например, этот статья дает довольно хороший обзор).
Моя текущая проблема заключается в том, что а) Я не уверен, почему я получаю так много эксклюзивных блокировок в моих файлах журнала базы данных PG и б) почему эти замки вообще случаются.
Я использую PostgreSQL 10 (+ расширение PostGIS) с 300 миллионами строк в 5 таблицах (200 ГБ). У меня есть около 5 скриптов (4x PHP и 1x Python Psycopg2), работающих 24/7, которые делают много вставок (и DO UPDATE
с COALESCE
В случае, если запись уже существует). Тем не менее, насколько я понимаю, расширение PHP Postgres фиксирует автоматически после каждого SQL-запроса и в моем скрипте Python увеличение коммитов существенно не уменьшает блокировки. У меня есть пара триггеров, которые динамически обновляют строки, но, насколько я могу судить по файлам журналов, они не являются причиной блокировок. Обычно бывает очень редко, чтобы два или более моих сценария одновременно вставляли / обновляли одну и ту же строку.
Это пример записи в журнале:
2018-01-31 01:04:02 CET [808]: [258-1] user=user1,db=maindb,app=[unknown],client=::1 LOG: process 808 still waiting for ExclusiveLock on page 0 of relation 26889 of database 16387 after 1015.576 ms
2018-01-31 01:04:02 CET [808]: [259-1] user=user1,db=maindb,app=[unknown],client=::1 DETAIL: Process holding the lock: 680. Wait queue: 1728, 152, 808.
2018-01-31 01:04:02 CET [808]: [260-1] user=user1,db=maindb,app=[unknown],client=::1 STATEMENT:
INSERT INTO "table1" (...)
VALUES (...)
ON CONFLICT (...)
DO UPDATE SET
...;
У меня есть подобные записи журнала каждые 2-3 минуты. Они проблематичны? Что именно они означают, окончательно ли решены блокировки или потеряны данные транзакции? В журнале нет записи о том, что блокировки разрешены или обновления окончательно зафиксированы в базе данных.
Второй тип частой записи в журнале похож на это:
2018-01-31 07:22:16 CET [2504]: [16384-1] user=,db=,app=,client= LOG: checkpoint complete: wrote 9999 buffers (3.8%); 0 WAL file(s) added, 0 removed, 7 recycled; write=269.842 s, sync=0.218 s, total=270.123 s; sync files=85, longest=0.054 s, average=0.002 s; distance=66521 kB, estimate=203482 kB
2018-01-31 07:22:46 CET [2504]: [16385-1] user=,db=,app=,client= LOG: checkpoint starting: time
Означает ли это Auto-Vaccum или Auto-Commit, который разрешает все блокировки?
Мой общий вопрос: должен ли я быть обеспокоенным и что-то делать или просто оставить все как есть?
Через некоторое время я выяснил, что вызывает эти блокировки, а также как их решить. Все эксклюзивные блокировки произошли по одному отношению в базе данных:
...ExclusiveLock on page 0 of relation 26889 of database...
Что такое 26889?
SELECT relname FROM pg_class WHERE OID=26889
Результат: idx_post_hashtags
Все это было вызвано индексом GIN для определенного столбца с массивом (текст). Кроме того, этот индекс GIN был бесполезен, так как массив имел переменную длину, и поиск какого-либо конкретного значения массива не принес выгоды от индекса. Я бросил это: все Эксклюзивные Замки исчезли!
Внимательное чтение журналов действительно помогает.
Других решений пока нет …