awesome-everything EN
↑ Обратно к восхождению

Базы данных

SSI и production-тюнинг autovacuum

Суть SSI отслеживает rw-антизависимости для ловли write skew; production autovacuum требует per-table override; аналитику с реплики нужно маршрутизировать с hot_standby_feedback=off чтобы разделить primary bloat.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 18 min

Production OLTP-кластер внезапно логирует сотни ошибок “could not serialize access” в минуту на таблице orders. У тебя 15 минут до эскалации. Путь диагностики — подтверждение уровня изоляции, счётчик предикатных блокировок, подлинность конфликта — это пошаговая процедура, не угадывание.

Внутренности SSI

Postgres 9.1 ввёл SSI по статье Cahill, Röhm и Fekete (2008). Механизм:

  1. Каждое чтение отслеживает «предикатные блокировки» — лёгкие, в памяти, ссылки на «я прочитал этот набор»
  2. Каждая запись отслеживает rw-антизависимости — «эта транзакция записала что-то, что соответствовало моему предикату, после того как я прочитал»
  3. На коммите, если транзакция часть «опасной структуры» — цикла rw-антизависимостей — SSI откатывает её с SQLSTATE 40001 could not serialize access due to read/write dependencies

Математика консервативна: SSI иногда откатывает транзакции, которые закоммитились бы безопасно (false positive корректны, но стоят throughput), но никогда не пропускает non-serializable расписание.

Ограничение памяти: предикатные блокировки ограничены max_pred_locks_per_transaction × max_connections. Под нагрузкой блокировки грубеют: row → page → relation, поднимая долю false positive.

Операционно: отслеживай частоту SQLSTATE 40001 в логах. Если превышает несколько процентов от коммитов — давление блокировок выходит за бюджет.

Диагностика SSI-кризиса

Проследи
1/5

Production OLTP-кластер внезапно логирует сотни ошибок 'could not serialize access' в минуту на таблице orders. Проследи диагностику.

1
Step 1 of 5
Шаг 1: Что сообщение ошибки говорит про уровень изоляции?
2
Locked
Шаг 2: Как подтвердить уровень изоляции, который использует приложение?
3
Locked
Шаг 3: Подтверждён SERIALIZABLE. Какая метрика говорит — давление нагрузки или ошибка конфига?
4
Locked
Шаг 4: pg_locks показывает грубение предикатных блокировок с row до page. Что настраиваешь?
5
Locked
Шаг 5: После тюнинга частота ошибок остаётся высокой. Какая следующая гипотеза?

Production-тюнинг autovacuum

Дефолтные ручки слишком мягкие для любой высоконагруженной таблицы. Per-table override:

ALTER TABLE orders SET (
  autovacuum_vacuum_scale_factor = 0.05,   -- запуск на 5% мёртвых (вместо 20%)
  autovacuum_vacuum_cost_limit = 2000,      -- высокий IO-бюджет за цикл
  autovacuum_vacuum_cost_delay = 2          -- 2мс задержки (0 на NVMe)
);

Для NVMe: cost_delay = 0. Для burst-нагрузок — дополнительно VACUUM (PARALLEL 4) orders; ночью по cron.

Кластерные ручки: autovacuum_max_workers = 6–8 на больших хостах; воркеры конкурируют за слоты в max_worker_processes.

Мониторинг прогресса live:

SELECT phase, heap_blks_scanned, heap_blks_total,
       index_vacuum_count
FROM pg_stat_progress_vacuum
WHERE relid = 'orders'::regclass;

Фазы: scanning heapvacuuming indexesvacuuming heapcleaning up indexestruncating heapperforming final cleanup.

Observability: метрики, которые реально двигаются

  • pg_stat_all_tables.n_dead_tup + n_live_tup — доля bloat per-table
  • pg_stat_user_tables.last_autovacuum, last_autoanalyze — отставание уборки
  • pg_stat_activity WHERE backend_xmin IS NOT NULL ORDER BY backend_xmin — кто пинит oldest-xmin
  • pg_stat_replication_slots.xmin — bloat, удерживаемый slot
  • pg_stat_database.deadlocks + pg_stat_database_conflicts — контеншн
  • pg_stat_database.xact_commit + xact_rollback — transaction throughput
  • Log-scraping на SQLSTATE 40001 — SSI false-positive rate
  • SELECT datname, age(datfrozenxid), age(datminmxid) FROM pg_database — алерты на 1B/1.2B

Расширения: pgstattuple (физическое состояние страниц), pg_buffercache (cache occupancy). Prometheus: pg_exporter, postgres_exporter.

HOT-доля и fillfactor

Мониторинг HOT: pg_stat_all_tables.n_tup_hot_upd / n_tup_upd. Выше 80% — хорошо; ниже 50% — fillfactor слишком агрессивный или неправильный набор индексов. pgstattuple выдаёт tuple_count, dead_tuple_count, free_space per-table для детального осмотра.

Tradeoff: стратегия изоляции для банка

Выбери лучший вариант

Сервис перевода денег банка двигает суммы между счетами. Выбери стратегию изоляции, лучше всего балансирующую корректность, throughput и операционную сложность.

DesignPrompt: autovacuum-политика

Спроектируй

Спроектируй политику autovacuum для высоконагруженной OLTP-таблицы, получающей 5 000 вставок и обновлений в секунду, с целевой долей мёртвых tuple ниже 10% и нулевым влиянием на пользовательскую latency.

  • Таблица 200 ГБ, рост 2–3 ГБ в день.
  • Хранилище NVMe, single-tenant.
  • Приложение периодически открывает 5-минутные аналитические транзакции с реплики.
  • Customer-facing p99 должна остаться под 50 мс во время autovacuum.
  • Окон downtime нет.

Проверь себя

Викторина

Postgres логирует 'cannot remove tuples deleted by transactions in progress' при autovacuum на 200 ГБ orders. Самая вероятная корневая причина?

Викторина

SSI логирует 8% ошибок 40001 от всех коммитов. Первый шаг диагностики?

Вспомните перед уходом
  1. 01
    Объясни, как ломается HOT-цепочка и какие наблюдаемые симптомы говорят, что это происходит слишком часто.
  2. 02
    Банк настаивает на SERIALIZABLE для переводов. Throughput на пике в 5 раз ниже чем под READ COMMITTED. DBA предлагает READ COMMITTED + SELECT FOR UPDATE. Compliance переживает за корректность. Кто прав и почему?
Recap
  • SSI: предикатные блокировки + rw-антизависимости + обнаружение цикла на коммите = SQLSTATE 40001
  • Память ограничена max_pred_locks_per_transaction × max_connections; при нехватке блокировки грубеют (row→page→relation)
  • >5% ошибок 40001 от коммитов → диагностировать давление предикатных блокировок
  • Per-table autovacuum override: scale_factor = 0.02–0.05, cost_limit = 2000–4000, cost_delay = 0 на NVMe
  • hot_standby_feedback = off на аналитических репликах — защищает primary autovacuum
  • Мониторинг: pg_stat_progress_vacuum.phase, n_dead_tup ratio, backend_xmin oldest holder, slot xmin
Связанные уроки
встречается в140
Продолжить восхождение ↑Реальные провалы MVCC, deployment-паттерны и распределённые снимки
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.