Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MVCC and GC Operator Minimum

Минимальный операторский контракт для triage GC/MVCC поведения.

Goal

Сделать GC предсказуемым:

  • видеть lag и stall;
  • ограничивать pause budget;
  • понимать, какие knobs крутить первыми.

Metrics to watch

  • Watermark:
  • angarabase_gc_watermark_snapshot
  • Slice latency:
  • angarabase_gc_compact_slice_duration_ms_*
  • GC progress:
  • angarabase_gc_compact_slices_total
  • angarabase_gc_compact_tables_scanned_total
  • angarabase_gc_compact_versions_removed_total
  • angarabase_gc_compact_tables_removed_total
  • Long snapshot risk:
  • txn_oldest_snapshot_age_seconds
  • txn_long_snapshot_warn_total
  • txn_long_snapshot_hard_total

Core knobs

  • ANGARABASE_GC_BUDGET_TABLES
  • ANGARABASE_GC_BUDGET_MS
  • ANGARABASE_GC_BUDGET_VERSIONS
  • ANGARABASE_GC_BURST_SLICES
  • ANGARABASE_GC_BURST_MAX_MS
  • ANGARABASE_GC_CURSOR_FILE (best-effort persisted cursor)

Полные настройки: src/operations/config-schema.md.

Triage: “GC not keeping up”

  1. Проверить txn_oldest_snapshot_age_seconds: большой age ограничивает watermark по контракту.
  2. Проверить хвост gc_compact_slice_duration_ms_*: при росте уменьшать slice budget.
  3. Проверить тренд *_versions_removed_total и *_tables_scanned_total: если нет прогресса, искать long snapshot и проблемы среды через diagnostics bundle.

UndoStore GC (RM-0.6.5.20)

С RM-0.6.5.20 введён epoch-based UNDO log GC:

Как работает

  • UndoGcWorker запускается как фоновый поток при старте сервера
  • Каждые ~60 секунд (интервал конфигурируемый) для каждого DB вычисляется gc_watermark
  • UndoStore::gc_purge_older_than(gc_watermark) удаляет записи старше watermark
  • Watermark = committed_epoch minus safety margin (защищает активные read-only транзакции)

Метрика

angarabase_undo_purged_records_total — gauge, показывающий прогресс очистки UNDO записей. Обновляется при активном GC.

Диагностика

SELECT * FROM sys.metrics WHERE name LIKE '%undo%';
-- Ожидаемо: angarabase_undo_purged_records_total > 0 при write нагрузке

Troubleshooting (UNDO GC не работает): Если angarabase_undo_purged_records_total долго равен 0 при активных UPDATE/DELETE:

  1. Проверить txn_oldest_snapshot_age_seconds — долгие (зависшие) транзакции блокируют продвижение gc_watermark.
  2. Найти и завершить зависшие транзакции (kill).
  3. Проверить логи сервера на наличие ошибок UndoGcWorker (например, ошибки I/O с .aud файлами).

Ручная компактификация heap файла

# one-shot compact для конкретной БД:
bash tools/golden_db/manage.sh compact <db_name>

Используй после bulk DELETE / большого числа UPDATE, если .adb файл подозрительно большой.

Index GC (Background Sweep)

В RM-0.6.6.8 реализован механизм фоновой очистки индексов (Index GC). В отличие от HeapStore, где удаление может быть физическим сразу, B-tree индексы используют логическое удаление (mark_deleted) для соблюдения Snapshot Isolation.

  • Knob: index_gc_interval_ms (ENV: ANGARABASE_INDEX_GC_INTERVAL_MS, default: 30000)
  • Что делает: Фоновый воркер сканирует страницы B-tree и физически удаляет записи, логически помеченные как удалённые, если они старше oldest_active_snapshot (watermark).
  • Метрика: angarabase_index_gc_entries_collected_total — счётчик записей, физически удалённых из индексов фоновым воркером.

State-Based Preemptive Sweep (RM-0.6.6.11)

С RM-0.6.6.11 IndexGC worker отслеживает долю «мёртвых» записей в реальном времени:

  • Gauge: angarabase_index_gc_dead_fraction — доля мёртвых записей (dead / total), диапазон 0–1.
  • Trigger: при превышении порога 0.15 (15%) worker запускает внеплановый sweep без ожидания таймера.
  • Sweep limit: ANGARABASE_INDEX_GC_MAX_SWEEP_PAGES (default: 3000 страниц за один sweep) — ограничивает I/O нагрузку GC.

Логика поведения:

  • При dead_fraction ≤ 0.15: GC работает по таймеру index_gc_interval_ms.
  • При dead_fraction > 0.15: в конце текущего GC-цикла автоматически запускается дополнительный background sweep (в рамках того же worker-тика, не синхронно на каждый DELETE).
  • Sweep limit не меняет число таймерных запусков — только ограничивает размер одного прохода.

Примечание: angarabase_index_gc_dead_fraction — это агрегированная метрика по всем индексам в рамках одного IndexStore. Она не детализирует горячие индексы по отдельности.

Когда менять index_gc_interval_ms

Уменьшить (например, до 5000 мс) при следующих симптомах:

  • angarabase_index_gc_entries_collected_total растёт быстро, но индексные сканы замедляются — GC не успевает за темпом DELETE/UPDATE.
  • EXPLAIN для индексного диапазонного запроса на hot-таблице показывает больше строк, чем ожидается (накопление логически удалённых записей увеличивает I/O при сканировании).

Увеличить (например, до 60000 мс) если:

  • Наблюдается фоновое I/O давление коррелирующее с GC циклом при сканировании продакшн запросов (проверяй angarabase_buffer_pool_miss_total и wait_events на BufferPoolEviction в момент GC sweep).

Мониторинг Index GC (PromQL)

# Скорость очистки (entries/sec) — растёт при heavy DELETE/UPDATE нагрузке
rate(angarabase_index_gc_entries_collected_total[5m])

# Алерт: если скорость внезапно упала до 0 при активных DML — GC воркер завис
rate(angarabase_index_gc_entries_collected_total[10m]) == 0

# Алерт: dead fraction растёт выше 20% — GC не успевает очищать
angarabase_index_gc_dead_fraction > 0.20

Troubleshooting: angarabase_index_gc_dead_fraction стабильно > 0.20:

При dead_fraction > 0.15 таймер уже не ограничивает частоту sweep — узким местом становится лимит страниц за один проход. Увеличь ANGARABASE_INDEX_GC_MAX_SWEEP_PAGES (например, до 5000–10000) и наблюдай за снижением dead_fraction. Уменьшение index_gc_interval_ms в этом сценарии не даёт эффекта.

Columnar Storage GC (RM-0.6.6.11)

Для колоночных (tiered columnar) таблиц с RM-0.6.6.11 введены два дополнительных GC-механизма.

Manifest GC (Ghost Segment Cleanup)

Проблема: В ManifestLog могут накапливаться ссылки на сегменты, физически отсутствующие в BlobStore («ghost refs» — например, после неполной compaction или crash). Такие ссылки приводят к ложным I/O ошибкам при сканировании.

Механизм: ManifestGcWorker периодически сверяет Live-сегменты в ManifestLog с содержимым BlobStore и выставляет Tombstone для отсутствующих сегментов. Учитывает snapshot isolation — сегменты, видимые активным транзакциям, не трогаются.

  • Config: ANGARABASE_COLUMNAR_MANIFEST_GC_INTERVAL_MS (default: 60000 мс)
  • Метрика: angarabase_columnar_manifest_gc_removed_total — счётчик ghost-ссылок, убранных с момента старта.
# Скорость удаления ghost refs — должна быть > 0 если в системе есть columnar GC:
rate(angarabase_columnar_manifest_gc_removed_total[5m])

Delete Vector (DV) Purge

Механизм: Compactor во время L0→L1 merge пропускает сегменты, полностью перекрытые Delete Vectors (100% строк помечены удалёнными), тем самым физически их убирая без отдельного pass. Метрика считает сегменты, пропущенные по этой причине.

  • Метрика: angarabase_columnar_compactor_dv_purged_total — сегменты, пропущенные при compaction (физически удалены как пустые).
# DV-purge throughput (сегменты/сек) при активном compaction:
rate(angarabase_columnar_compactor_dv_purged_total[5m])

Cooperative GC (Inline Micro-Vacuum)

Дополнительно к фоновому воркеру, в RM-0.6.6.8 внедрен механизм Cooperative GC.

  • Как работает: Foreground операции (такие как lookup или range_scan) при обнаружении мертвых версий записей (старше oldest_active_snapshot) автоматически помечают их или выполняют немедленную очистку, если страница заблокирована эксклюзивно.
  • Настройка: Отдельного knob нет, интенсивность регулируется общим watermark через index_gc_interval_ms.
  • src/operations/diagnostics-bundle.md
  • src/operations/performance-tuning.md