Как реализовать get or create в PostgreSQL без гонок и раздувания таблицы
Обстоятельный разбор операции: вернуть существующую строку или создать новую, не обновляя совпавшие данные, как при upsert. На таблице тегов видно, почему SELECT перед INSERT даёт идемпотентность, но ломается при двух одновременных запросах.
Карта решений:
1. Перехват нарушения уникальности закрывает гонку, но неудачная вставка оставляет мёртвую строку до очистки;
2. 50 000 попыток вставить существующий тег заняли около 12 секунд и увеличили таблицу с 8192 байт до 1776 КБ;
3. VACUUM убрал мёртвые строки и вернул размер к 8192 байтам. Обычно очистку по заданным порогам запускает autovacuum.
Читайте статью, если синхронизируете справочники под нагрузкой. Проверьте долю конфликтов: при частых дублях перехват исключений создаёт мёртвые строки и добавляет работы autovacuum.
Post #3028
148
