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_totalangarabase_gc_compact_tables_scanned_totalangarabase_gc_compact_versions_removed_totalangarabase_gc_compact_tables_removed_total- Long snapshot risk:
txn_oldest_snapshot_age_secondstxn_long_snapshot_warn_totaltxn_long_snapshot_hard_total
Core knobs
ANGARABASE_GC_BUDGET_TABLESANGARABASE_GC_BUDGET_MSANGARABASE_GC_BUDGET_VERSIONSANGARABASE_GC_BURST_SLICESANGARABASE_GC_BURST_MAX_MSANGARABASE_GC_CURSOR_FILE(best-effort persisted cursor)
Полные настройки: src/operations/config-schema.md.
Triage: “GC not keeping up”
- Проверить
txn_oldest_snapshot_age_seconds: большой age ограничивает watermark по контракту. - Проверить хвост
gc_compact_slice_duration_ms_*: при росте уменьшать slice budget. - Проверить тренд
*_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:
- Проверить
txn_oldest_snapshot_age_seconds— долгие (зависшие) транзакции блокируют продвижениеgc_watermark. - Найти и завершить зависшие транзакции (kill).
- Проверить логи сервера на наличие ошибок
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.
Related runbooks
src/operations/diagnostics-bundle.mdsrc/operations/performance-tuning.md