AngaraBase
Реляционная СУБД с протоколом PostgreSQL и предсказуемым поведением.
Написана на Rust. Текущая ветка — 0.6.x.
AngaraBase разработана для нагрузок типа ERP/SaaS, где предсказуемость важнее «магии», а каждое поведение фиксируется явным контрактом.
Здесь — то, что уже работает в коде на текущей ветке. Roadmap-фичи помечены отдельно. AngaraBase — молодой проект, и мы предпочитаем точность маркетинговым обещаниям.
С чего начать
Выберите вход по своей роли:
| Кто вы | Куда идти |
|---|---|
| Знакомлюсь с продуктом | Что такое AngaraBase → Архитектура с высоты птичьего полёта |
| Хочу попробовать локально | Quickstart за 5 минут |
| Разработчик приложения | SQL compatibility → Data types → Known issues |
| DBA / SRE | Installation → Configuration → Backup/Restore → Operations runbooks |
| Security engineer | Security model → Hardening → Audit |
| Contributor / Researcher | Architecture overview → Layering and Boundaries → Glossary |
| Сообщаю о проблеме | Support flow |
Ключевые особенности
Совместимость с PostgreSQL без сюрпризов
- Стандартный pgwire-протокол:
psql, JDBC, psycopg, node-postgres, pgx, Npgsql работают как с обычным PostgreSQL. - Контрактное подмножество SQL: что поддерживается — поддерживается полностью; что не поддерживается —
возвращает явный SQLSTATE (
0A000и др.), а не молчаливый bypass. - Pinned-тесты совместимости (compat suite) как доказательство, а не «процент совместимости».
Подробнее: SQL compatibility overview.
Современный движок: MVCC через UNDO-log, а не через bloat
В отличие от PostgreSQL, AngaraBase хранит исторические версии строк в отдельном UNDO-логе (как Oracle/InnoDB), а не в самой таблице. В результате:
- heap-страницы содержат только текущие версии строк → меньше bloat;
VACUUMв привычном смысле не нужен — старые версии очищает фоновый AngaraGC по чёткому контракту;- видимость для транзакций определяется детерминированно по snapshot.
Подробнее: Транзакции и MVCC.
Pluggable storage с первого дня
- Row-store (baseline) — для OLTP.
- AngaraMemory — in-memory таблицы с тремя уровнями durability (
none/logged/snapshotted) и hard row-cap. - AngaraColumn — columnar storage для аналитики (в roadmap; HTAP-направление).
Выбор движка делается при CREATE TABLE ... WITH (storage='memory'|'row'|...).
Подробнее: Storage engine.
Cost-based оптимизатор и vectorized execution
- AngaraPlan — CBO с robust-планированием, устойчивым к ошибкам в оценках.
- AngaraStat — статистика: HLL для NDV, equi-height histograms, MCV (reservoir sampling).
- AngaraFlow — streaming-исполнение (Volcano).
- AngaraVector — vectorized путь для scan/filter/project/join/aggregate; режимы
auto/force_vector/force_row. ВEXPLAINявно отмечаетсяVectorHashJoin,VectorAggи др. - AngaraParallel — partitioned parallel join, DOP-капы (
ANGARABASE_PARALLEL_DOP_CAP_*).
Подробнее: Query processing.
Многоуровневая защита с явными контрактами
Безопасность встроена в ядро, а не «прикручена» сверху. Шесть слоёв защиты, каждый с собственным контрактом:
- Транспорт и идентичность — TLS, SCRAM, cert-аутентификация.
- RBAC — кому вообще разрешено.
- RLS v1 — какие строки видны и изменяемы.
- Break-glass — единственный путь обхода RLS (даже
SUPERUSERего не имеет), всегда с REASON, TTL и аудитом. - Audit chain — append-only, tamper-evident (SHA-256 chain).
- TDE — шифрование страниц, WAL и audit-sink; fail-closed без ключа.
Подробнее: Security model.
Эксплуатация под предсказуемость
- Per-database backup и restore (cold + online/PITR baseline).
- Ясная диагностика:
EXPLAIN/EXPLAIN ANALYZE,sys.*views (sys.identity,sys.health,sys.settings,sys.tables,sys.column_stats,angara_stat_activity,angara_stat_statements). - Структурированное логирование, OpenTelemetry-style spans, USDT/eBPF probes.
- Метрики Prometheus:
angara_*именованные подсистемы видно в логах, метриках иEXPLAIN. - Native-пакеты RPM/DEB, init-first service start fence, systemd-юниты.
Подробнее: Operations runbooks.
Принципы проекта (явная позиция)
| Принцип | Что это значит |
|---|---|
| Restrictive by default | Строгие проверки и аутентификация по умолчанию. Обходы — только явным флагом |
| Contract-first | Каждая фича имеет явный контракт: что поддержано, какой SQLSTATE при отказе, какие инварианты |
| Fail-closed | При неопределённости — явная ошибка, а не «как-нибудь сработает» |
| Evidence-first | Корректность доказывается артефактами тестов, а не маркетингом |
| PostgreSQL-friendly | Никаких собственных клиентов: вся совместимость — через pgwire |
| Минимум зависимостей | Меньше runtime dependencies → меньше supply-chain поверхности |
Полная декларация: Project principles.
Документация по разделам
Знакомство (Tutorials)
Концепции (Explanation)
- Хранение данных — row-store, страницы, slotted pages, pluggable storage
- Транзакции и MVCC — UNDO-log MVCC, изоляция, GC
- Индексы — AngaraTree (B+tree, BRIN), IndexStore
- Обработка запросов — AngaraPlan, AngaraStat, AngaraFlow, AngaraVector
- Каталог и метаданные — SysCatalog и
sys.*views - Жизненный цикл инстанса — init, startup, recovery, shutdown
SQL Reference (Reference)
- Обзор совместимости — политика, SQLSTATE-коды, vector execution
- Типы данных — поддерживаемые типы, casting, NULL
- DDL — CREATE/ALTER/DROP, индексы, ограничения
- DML — INSERT, UPDATE, DELETE, mutation policies
- Запросы — CTE, JOIN, агрегаты, ORDER BY
- Секционирование — RANGE/LIST partitioning, routing, pruning
Безопасность (How-to)
- Модель безопасности
- Аутентификация
- Авторизация (RBAC + RLS)
- Аудит
- Шифрование (TDE + клиентское)
- Break-glass
- Hardening runbook
- GOST-совместимость
Эксплуатация (How-to)
- Установка — portable archive, RPM/DEB, source build
- Конфигурация — TOML, env,
sys.settings - Резервное копирование и восстановление — cold + online/PITR
- Crash recovery — host migration, WAL replay
- Обновление версии
- Мониторинг — Prometheus, Grafana, health probes
- Диагностика — EXPLAIN, slow log,
sys.* - Логирование, Tracing, USDT/eBPF probes
- GC auto-tuning
- Error debug runbook (10 минут)
- GOST crypto setup
- Verify release artifacts
Operator deep-dives — runbooks (Reference)
- Operations overview
- Runbooks index
- Troubleshooting guide
- Disaster recovery playbook
- Performance tuning guide
- MVCC and GC operator minimum
- Diagnostics bundle runbook
- Security operations baseline
- Upgrade and migration
- Backup and restore (operator-level)
- Configuration schema reference
- Observability metrics checklist
- jemalloc heap profiling runbook
- Parallel runtime observability runbook
- Replication v2 operations guide
- Operational policies baseline
- Client compatibility baseline (operator)
- Testing and validation baseline
- Golden dataset management
- CI reproducibility contract
- Known issues baseline (operator)
Architecture (Reference)
Справочник (Reference)
- Известные ограничения и SQLSTATE
- Глоссарий и именованные подсистемы
- Системные представления
sys.* - Совместимость клиентов
- Поддержка и сбор артефактов баг-репорта
- Generated reference (auto-generated registries)
История изменений
- AngaraBook changelog (highlights) — сжатая лента изменений с пользовательской точки зрения.
Сообщество и участие
Мы рады участникам сообщества:
- Нашли баг или regression? Соберите артефакты по Support flow и откройте issue.
- Хотите изменить поведение? Предложите RFC по процессу разработки проекта (внутренний контур).
- Хотите помочь с документацией? AngaraBook —
documentation-as-codeв этом же репозитории. Правила оформления: см. внутреннийWRITING_RULES.mdрядом с книгой. - Хотите следить за разработкой? Следите за changelog и release notes.
О документации
AngaraBook построена на принципах Diátaxis:
- Tutorials (Знакомство) — обучение через действие, для новых пользователей.
- How-to guides (Безопасность / Эксплуатация) — рецепты для конкретных задач.
- Reference (SQL / Architecture / Справочник) — точное описание поведения.
- Explanation (Концепции) — почему всё устроено так, а не иначе.
Гарантии качества:
- Документация — часть кода: правится в одном репозитории, проходит ту же CI, что и движок.
- Любое заявленное SQL/ops-поведение проверяется pinned-тестами или явно помечается как roadmap.
- Anti-drift: версии команд, конфигурационные ключи и SQLSTATE-коды сверяются автоматически.
- Public-сборка проходит security gate: внутренние процессы и конфиденциальные ссылки не попадают в публичный портал.
Если вы заметили несоответствие документации и реального поведения — это баг документации; пожалуйста, сообщите.
AngaraBase v0.6.x · Linux x86_64/aarch64 · glibc >= 2.28
Что такое AngaraBase
AngaraBase — реляционная СУБД на Rust, совместимая с протоколом и подмножеством SQL PostgreSQL. Проектируется для нагрузок типа ERP/SaaS, где важны предсказуемое поведение, явные границы и отсутствие «магии».
- Платформа сервера: Linux x86_64 / aarch64 (
glibc >= 2.28) - Клиенты: любая платформа через стандартные PostgreSQL-драйверы
- Текущая ветка:
0.6.x
AngaraBase — молодой проект. Эта документация описывает то, что уже работает в коде на текущей ветке, и явно отделяет это от того, что находится в roadmap.
Что вы получаете прямо сейчас
| Возможность | Состояние |
|---|---|
pgwire-протокол, подключение psql/JDBC/psycopg/pgx без модификаций | Доступно |
| Подмножество SQL PostgreSQL c явным контрактом и pinned-тестами | Доступно |
| Транзакции, MVCC (UNDO-log), уровни READ COMMITTED / REPEATABLE READ | Доступно |
| Per-database backup/restore (cold + online/PITR baseline) | Доступно |
| Многоуровневая безопасность: SCRAM/TLS, RBAC, RLS v1, audit chain, TDE, break-glass | Доступно |
| Индексы AngaraTree (B+tree, BRIN), статистика AngaraStat (HLL, гистограммы, MCV) | Доступно |
| Cost-based оптимизатор AngaraPlan, streaming-исполнение AngaraFlow | Доступно |
Vectorized execution AngaraVector (scan/filter/project/join/agg, режим auto/force_*) | Доступно (bounded) |
In-memory storage AngaraMemory (storage='memory', durability tiers) | Доступно (bounded) |
| Параллельное исполнение AngaraParallel (DOP-капы, partitioned join) | Доступно (bounded) |
| Columnar storage AngaraColumn, HTAP, distributed SQL | В roadmap (см. Architecture) |
Точные границы поддержки SQL и текущие ограничения зафиксированы в SQL compatibility overview и Known issues. AngaraBase не публикует «процент совместимости» — вместо этого приводит точный контракт.
Принципы
| Принцип | Что это значит на практике |
|---|---|
| Restrictive by default | По умолчанию строгие проверки, ограничения и аутентификация. «Магические» обходы требуют явного флага |
| Contract-first | Каждая фича имеет явный контракт (что поддержано, какой SQLSTATE при отказе, какие инварианты) |
| No semantic surprises | Неподдержанная конструкция возвращает явный SQLSTATE (0A000 и др.), а не молчаливый bypass |
| Fail-closed | При неопределённости система отклоняет запрос, а не пропускает его |
| Evidence-first | Корректность доказывается артефактами тестов и oracle-скриптами, не маркетингом |
| PostgreSQL-friendly | Совместимость по pgwire и SQL подмножеству; никакой собственной обвязки в клиенте |
Совместимость с PostgreSQL
AngaraBase реализует pgwire-протокол как первичный API. С точки зрения клиента это обычный PostgreSQL
endpoint:
psql "host=127.0.0.1 port=5432 user=angara_root dbname=base sslmode=verify-full"
| Стек | Драйвер | Статус |
|---|---|---|
| Python | psycopg2, psycopg3 | Поддерживается |
| Node.js | pg (node-postgres) | Поддерживается |
| Java | PostgreSQL JDBC | Поддерживается |
| Go | lib/pq, pgx | Поддерживается |
| .NET | Npgsql | Поддерживается |
| Tooling | psql, DBeaver | Поддерживается с оговорками — см. Client compatibility |
Полный compat-контракт и smoke-сценарии: SQL compatibility overview.
Чем AngaraBase отличается от PostgreSQL
| Область | PostgreSQL | AngaraBase |
|---|---|---|
| Pluggable storage | В работе (pg_am v2) | Встроено: row-store + AngaraMemory; AngaraColumn — в roadmap |
| MVCC | UNDO-in-heap (bloat, VACUUM) | UNDO-log (отдельный лог, heap содержит только текущие версии) |
| Backup/restore | Кластерный | Per-database, cold + online/PITR baseline |
| Безопасность | Расширения и конфигурация | Многослойная модель из коробки: RBAC + RLS + audit chain + TDE + break-glass |
| Именованные подсистемы | — | AngaraTree, AngaraStat, AngaraPlan, AngaraFlow, AngaraIO, AngaraGC, AngaraVector, AngaraMemory, AngaraParallel — каждая с явным контрактом и метриками |
| Поведение при unsupported SQL | Часто best-effort | Явный SQLSTATE, fail-closed |
| Совместимость как метрика | Полный SQL | Контрактное подмножество с pinned-тестами и публичным known-issues регистром |
Кому подходит
- Командам ERP/SaaS (например, на базе Odoo), которым нужна предсказуемая PostgreSQL-совместимая БД с явным контрактом совместимости.
- DBA, ценящим явные границы поведения, а не «best-effort» совместимость.
- Инженерам, которым важно понимать, что именно поддерживается, и иметь reproducible-тесты как доказательство.
- Сообществу, готовому участвовать в формировании молодой СУБД.
Что AngaraBase не делает (на текущей ветке)
- Не предоставляет distributed SQL и multi-master HA — это горизонт следующих major-веток.
- Не реализует полный SQL PostgreSQL — только контрактное подмножество с явной границей.
- Не маскирует неподдержанные фичи — вы получаете явную ошибку с SQLSTATE.
- Не работает на не-Linux серверах. Клиенты — кросс-платформенные.
С чего начать
| Вы | Куда идти |
|---|---|
| Знакомитесь впервые | Архитектура «с высоты птичьего полёта» |
| Хотите запустить локально | Быстрый старт |
| Оцениваете пригодность для своего стека | SQL compatibility overview, Known issues |
| Планируете продакшен-развёртывание | Установка, Безопасность, Hardening |
| Сообщаете об ошибке | Поддержка |
Ссылки
- Quickstart — собрать, запустить, выполнить первый SQL за несколько минут.
- Architecture — как устроена БД внутри.
- SQL reference — какой SQL поддерживается.
- Security model — модель безопасности.
- Operations — конфигурация и эксплуатация.
- Glossary — термины и именованные подсистемы.
Архитектура AngaraBase
Этот документ даёт понимание внутреннего устройства AngaraBase на уровне, достаточном для принятия решений: выбор конфигурации, диагностика проблем, оценка применимости.
Подробная техническая спецификация: docs/01_ARCHITECTURE.md.
Многоуровневая архитектура
AngaraBase состоит из шести слоёв. Каждый слой имеет своё API и зависит только от слоёв ниже. Это позволяет заменять реализации (например, storage engine) без изменения остальных слоёв.
┌──────────────────────────────────────────────────────────────┐
│ TIER 1: CLIENT LAYER (Wire Protocol) │
│ │
│ • pgwire-протокол (совместимость с psql, JDBC, и др.) │
│ • connection pooling │
│ • async event loop │
└─────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────┴────────────────────────────────────┐
│ TIER 2: SESSION / TRANSACTION LAYER │
│ │
│ • сессии и переменные сессии │
│ • управление транзакциями (BEGIN/COMMIT/ROLLBACK/SAVEPOINT) │
│ • уровни изоляции (READ COMMITTED, REPEATABLE READ) │
│ • блокировки и обнаружение deadlock'ов │
└─────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────┴────────────────────────────────────┐
│ TIER 3: QUERY EXECUTION LAYER │
│ │
│ • парсинг SQL-запроса │
│ • семантическая валидация и проверка типов │
│ • планирование и оптимизация (AngaraPlan) │
│ • выполнение физического плана (AngaraFlow) │
└─────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────┴────────────────────────────────────┐
│ TIER 4: CATALOG & TYPE SYSTEM │
│ │
│ • реестр таблиц, схем, баз данных │
│ • реестр типов, функций, операторов │
│ • реестр индексов (access methods) │
│ • системные представления sys.* │
└─────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────┴────────────────────────────────────┐
│ TIER 5: STORAGE LAYER (Pluggable Storage) │
│ │
│ • row-store engine (OLTP baseline) │
│ • pluggable: in-memory и column-store (планируются) │
│ • индексы (AngaraTree: B+tree, BRIN) │
│ • Transaction Log (WAL) — журнал транзакций │
└─────────────────────────┬────────────────────────────────────┘
│
┌─────────────────────────┴────────────────────────────────────┐
│ TIER 6: SYSTEM LAYER │
│ │
│ • буферный менеджер и page cache │
│ • метрики и телеметрия │
│ • восстановление после сбоев (crash recovery) │
│ • планировщик ресурсов (CPU, память, I/O) │
└──────────────────────────────────────────────────────────────┘
Что это значит для вас
- TIER 1: вы подключаетесь стандартным PostgreSQL-клиентом — ничего специального устанавливать не нужно.
- TIER 2: транзакции работают привычным образом —
BEGIN,COMMIT,ROLLBACK,SAVEPOINT. - TIER 3: SQL-запросы проходят через парсер, оптимизатор и исполнитель.
EXPLAINпокажет план выполнения. - TIER 4: метаданные о таблицах, типах и индексах доступны через системные представления
sys.*(например,SELECT * FROM sys.tables). - TIER 5: данные хранятся в pluggable storage engine. Сейчас — row-store; в будущих версиях можно будет выбирать движок при создании таблицы.
- TIER 6: буфер, метрики и восстановление — инфраструктурный слой, который работает прозрачно. Вы взаимодействуете с ним через конфигурацию и мониторинг.
Именованные компоненты
Ключевые подсистемы AngaraBase имеют собственные имена. Это упрощает диагностику, документацию и конфигурацию — когда вы видите имя в логах или метриках, вы знаете, к какой части системы оно относится.
| Компонент | Что делает | Статус |
|---|---|---|
| AngaraTree | Индексы: B+tree, BRIN | Доступен |
| AngaraStat | Статистика таблиц: NDV, гистограммы, MCV | Доступен |
| AngaraPlan | Cost-based оптимизатор запросов | Доступен |
| AngaraFlow | Streaming-исполнение запросов (iterator/Volcano модель) | Доступен |
| AngaraIO | Async I/O pipeline (storage, WAL, prefetch) | Доступен |
| AngaraGC | MVCC garbage collection (очистка устаревших версий строк) | Доступен |
| AngaraVector | Vectorized execution (SIMD-оптимизация) | Доступен |
| AngaraParallel | Параллельное выполнение запросов | Доступен |
| AngaraMemory | In-memory storage engine | Доступен |
Пример: если EXPLAIN показывает AngaraTree: Index Scan, это значит, что запрос использует B+tree-индекс.
Если в логах появляется AngaraGC, это сборщик устаревших версий строк.
Модель данных
AngaraBase использует четырёхуровневую иерархию (аналогично MS SQL Server):
Instance (процесс angarabased)
└─ Database
└─ Schema
└─ Table
- Instance — один запущенный процесс
angarabased. Может содержать несколько баз данных. - Database — изолированная база данных. Каждая БД имеет свои файлы данных, transaction log и настройки. Backup и restore работают на уровне отдельной базы.
- Schema — логическая группировка таблиц внутри базы (по умолчанию —
public). - Table — таблица с данными.
Пример:
angarabased (instance)
├─ Database "odoo_prod"
│ ├─ Schema "public"
│ │ ├─ Table "res_partner"
│ │ ├─ Table "sale_order"
│ │ └─ ...
│ └─ Schema "staging"
│ └─ ...
├─ Database "analytics"
│ └─ Schema "public"
│ └─ ...
└─ System catalog (sys.*)
Каждая база данных независима: backup odoo_prod не затрагивает analytics, и наоборот.
Иерархия конфигурации
Настройки в AngaraBase применяются на трёх уровнях, от самого широкого к самому узкому:
Instance (angarabase.conf)
└─ Database (ALTER DATABASE ... SET ...)
└─ Session (SET ...)
Более узкий уровень переопределяет более широкий:
- Instance — настройки сервера (порт, лимиты памяти, пути к файлам). Часть из них требует перезапуска.
- Database — настройки конкретной базы (лимиты, параметры storage). Применяются без перезапуска.
- Session — настройки текущего подключения (
SET timezone = 'Europe/Moscow'). Действуют до конца сессии.
Что это значит на практике
Архитектура AngaraBase спроектирована с учётом нескольких принципов, которые влияют на повседневную работу:
-
Подключение стандартными инструментами. pgwire-совместимость означает, что вам не нужны специальные драйверы или библиотеки.
psql, DBeaver, ваше приложение на Python или Java — всё подключается как к обычному PostgreSQL. -
Per-database изоляция. Каждая база данных — самостоятельная единица с точки зрения backup, restore и конфигурации. Это удобно для multi-tenant сценариев: каждый клиент может иметь свою БД с индивидуальными настройками и отдельным backup-расписанием.
-
Явная диагностика. Системные представления
sys.*дают доступ к метаданным и состоянию системы. Именованные компоненты (AngaraTree, AngaraPlan и др.) отражаются вEXPLAIN, логах и метриках — вы всегда знаете, какая часть системы задействована. -
Pluggable storage. Сейчас доступен row-store (оптимизирован для OLTP). В будущих версиях можно будет выбирать движок хранения при создании таблицы — in-memory для горячих данных, column-store для аналитики.
-
Fail-closed поведение. Если конструкция SQL не поддерживается — вы получите явную ошибку с SQLSTATE-кодом, а не неожиданный результат. Это предсказуемо и безопасно для продакшена.
Дополнительные материалы
- Canonical architecture doc:
docs/01_ARCHITECTURE.md— полная техническая спецификация. - Хранение данных:
concepts/storage-engine.md— row-store, страницы, pluggable storage. - Обработка запросов:
concepts/query-processing.md— парсер, планировщик, оптимизатор, исполнитель. - Каталог и метаданные:
concepts/catalog-and-metadata.md— SysCatalog и системные представления.
Quickstart (testing)
Goal
Поднять angarabased, подключиться через psql, выполнить базовый DDL/DML и убедиться, что pgwire работает.
Prerequisites
- Linux x86_64
- Один из вариантов установки:
- Rust toolchain (см.
rust-toolchain.toml) для source build, - или portable archive
x86_64-unknown-linux-gnu(glibc >= 2.28).
Install from portable archive
mkdir -p /opt/angarabase
tar -xzf angarabase-0.6.3-x86_64-unknown-linux-gnu.tar.gz -C /opt/angarabase
/opt/angarabase/angarabase-0.6.3/bin/angarabase-server --version
If runtime glibc is below baseline (2.28), angarabase-server exits fail-closed with an explicit
compatibility message.
Native package flow
For RPM/DEB deployments, service start is intentionally blocked before secure init:
angarabase-server --init /var/lib/angarabase --superuser admin --auth-mode scram --superuser-password-file /secure/path/pass.txt --require-auth
systemctl start angarabase
If you intentionally need trust bootstrap for isolated labs, it must be explicit:
angarabase-server --init /var/lib/angarabase --auth-mode trust --insecure-trust
Build
cargo build -p angarabase-server
cargo build -p angara-cli
Run server (local)
AngaraBase использует явную инициализацию инстанса (--init) перед обычным запуском.
Минимальный путь для тестирования (без ручного создания конфига):
- Выполните одноразовую инициализацию в директории инстанса.
target/debug/angarabase-server --init /tmp/angarabase-instance --superuser angara_root --superuser-password 'change-me' --auth-mode scram
По умолчанию будет создано:
data/в/tmp/angarabase-instance/datatxlog/в/tmp/angarabase-instance/txlog- конфиг
angarabase.confв/tmp/angarabase-instance/angarabase.conf
- Запустите сервер:
target/debug/angarabase-server --config /tmp/angarabase-instance/angarabase.conf
В этом сценарии используется SCRAM bootstrap user angara_root.
Для локального trust/no-auth режима можно явно запускать с --allow-insecure-no-auth.
SecurityContext note:
- In
scram/certmodes, protected SQL execution requires session context. - Minimal setup for tenant-scoped workloads:
SET SESSION CONTEXT 'app.tenant_id' = 'public';
Альтернативный путь (если вы хотите использовать существующий конфиг):
--config <path>при--initчитается как input-конфиг, если файл существует,- и записывается как output-конфиг, если файл не существует.
Примеры:
# init using an existing config (input)
target/debug/angarabase-server --config ./angarabase.conf --init
# init and write a new config (output; file must not exist)
target/debug/angarabase-server --config /tmp/angarabase.conf --init /tmp/angarabase-instance
Для локальной разработки допускается shortcut:
target/debug/angarabase-server --config angarabase.conf --dev
--dev сохраняет auto-init поведение только для dev/test сценариев.
Connect with psql
psql "host=127.0.0.1 port=5432 user=angara_root dbname=base password=change-me sslmode=disable"
Smoke SQL
CREATE TABLE t (id INT PRIMARY KEY, v INT);
INSERT INTO t (id, v) VALUES (1, 10);
INSERT INTO t (id, v) VALUES (2, 20);
SELECT * FROM t ORDER BY id;
Restart check (DDL survives restart)
CREATE TABLE metadata (catalog) should survive restart.
- Остановите сервер (Ctrl+C).
- Запустите снова.
- Проверьте, что таблица видна:
SELECT table_name FROM sys.tables WHERE table_name = 't';
Sys introspection (sys.*)
Примеры полезных запросов:
SELECT * FROM sys.identity;
SELECT * FROM sys.health;
SELECT * FROM sys.settings WHERE name IN ('server.addr','storage.data_directory');
SELECT * FROM sys.tables;
SELECT * FROM sys.columns WHERE table_name = 't';
Optional: SQL shutdown (fail-closed)
По умолчанию shutdown через SQL выключен. Чтобы включить (локально/для тестов):
export ANGARABASE_ALLOW_SQL_SHUTDOWN=1
После этого можно запросить shutdown из psql:
SELECT sys.request_shutdown();
If something fails
- Проверьте “Known issues”:
../reference/known-issues.md - Для подключения клиентов (DBeaver и др.):
../reference/client-compatibility.md - Для репорта багов соберите артефакты по
../reference/support.md.
Дальше
После того как сервер ответил psql -h 127.0.0.1 и базовый SELECT отработал, логичные следующие шаги:
- Что такое AngaraBase — продуктовый обзор: для чего проект, чем отличается от ванильного PostgreSQL.
- Обзор совместимости SQL — что из стандарта можно использовать прямо сейчас.
- Конфигурация — как поднять сервер не из дефолтов, а под свой сценарий.
- Модель безопасности — прежде чем пускать кого-либо ещё, кроме себя.
Подключение клиентов: psql, Python, JDBC
Что вы получите за 15 минут
После этого туториала у вас будут три рабочих способа подключения к локально запущенному инстансу AngaraBase:
psql— интерактивная консоль PostgreSQL.- Python через
psycopg[binary]— типичный скрипт приложения. - JDBC через стандартный
org.postgresql:postgresql— типичный Java/Kotlin/Scala-стек.
Все три способа работают через стандартный pgwire-протокол: AngaraBase представляется клиентам как PostgreSQL, поэтому никаких специальных драйверов не требуется.
Здесь описан гарантированно работающий минимальный путь. Полный список протестированных клиентов и нюансы конкретных GUI-инструментов (DBeaver, IntelliJ DataGrip и др.) — в отдельном справочнике Совместимость клиентов.
Prerequisites
- AngaraBase, поднятый локально по Quickstart. Считаем, что сервер слушает
127.0.0.1:5432, есть пользовательangaraи базаangara_demo. - Установленный
psql(любая версия PostgreSQL ≥ 13). - Python 3.10+ (для шага 2).
- JDK 17+ и Maven/Gradle (для шага 3).
Проверьте, что сервер отвечает:
psql --version
# psql (PostgreSQL) 16.4
ss -ltnp 'sport = 5432'
# LISTEN ... 127.0.0.1:5432 ...
Если порт не слушается — вернитесь к Quickstart и убедитесь, что angarabased запустился без
ошибок.
Шаг 1. psql — интерактивная консоль
1.1. Подключение
psql 'postgresql://angara@127.0.0.1:5432/angara_demo'
Пароль (если задан) — по подсказке. Признак успеха: приглашение angara_demo=>.
1.2. Минимальный сценарий: создать таблицу, вставить, выбрать
-- Внутри psql:
CREATE TABLE products (
id BIGINT PRIMARY KEY,
name TEXT NOT NULL,
price NUMERIC(10, 2) NOT NULL
);
INSERT INTO products (id, name, price) VALUES
(1, 'Coffee', 4.50),
(2, 'Tea', 3.00);
SELECT id, name, price FROM products ORDER BY id;
Ожидаемый вывод:
id | name | price
----+--------+-------
1 | Coffee | 4.50
2 | Tea | 3.00
(2 rows)
1.3. Полезные \-команды
| Команда | Назначение |
|---|---|
\dt | Список пользовательских таблиц текущей базы. |
\d products | Структура таблицы products (колонки, типы, индексы). |
\du | Список ролей (RBAC). |
\timing on | Включить вывод времени каждого запроса. |
\q | Выйти из psql. |
1.4. Если что-то пошло не так
could not connect to server: Connection refused— сервер не запущен или слушает не127.0.0.1. Проверьтеss -ltnp 'sport = 5432'и логиangarabased.authentication failed for user "angara"— пароль не задан или не совпадает. См. Аутентификация.feature_not_supported (0A000)— вы попали в SQL-конструкцию, которую AngaraBase не поддерживает. Это явный fail-closed контракт; см. Известные ограничения и SQLSTATE.
Шаг 2. Python через psycopg
2.1. Установка драйвера
Используем psycopg версии 3 (бинарный wheel — без локальной компиляции):
python3 -m venv .venv
source .venv/bin/activate
pip install 'psycopg[binary]>=3.1,<4'
2.2. Минимальный скрипт
Создайте файл connect_demo.py:
import psycopg
DSN = "postgresql://angara@127.0.0.1:5432/angara_demo"
with psycopg.connect(DSN) as conn:
with conn.cursor() as cur:
cur.execute(
"INSERT INTO products (id, name, price) VALUES (%s, %s, %s)",
(3, "Espresso", 4.25),
)
cur.execute("SELECT id, name, price FROM products ORDER BY id")
for row in cur.fetchall():
print(row)
conn.commit()
Запуск:
python3 connect_demo.py
Ожидаемый вывод:
(1, 'Coffee', Decimal('4.50'))
(2, 'Tea', Decimal('3.00'))
(3, 'Espresso', Decimal('4.25'))
2.3. Что важно знать про Python-клиент
- Параметризованные запросы обязательны. Не подставляйте значения через
f"...{value}..."— это путь к SQL-инъекциям.psycopgподставляет параметры на стороне драйвера через серверный prepared statement. with conn:иconn.commit()— разные вещи. Контекст-менеджерwith conn:гарантирует закрытие соединения, но не делает автокоммит. Транзакция фиксируется только явнымconn.commit().- AngaraBase предсказуемо возвращает SQLSTATE. Перехватывайте
psycopg.errors.FeatureNotSupportedи проверяйтеe.diag.sqlstate == "0A000", чтобы корректно обрабатывать неподдерживаемые конструкции (контракт fail-closed).
Шаг 3. JDBC через org.postgresql:postgresql
3.1. Зависимость
Maven (pom.xml):
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.4</version>
</dependency>
Gradle (build.gradle.kts):
dependencies {
implementation("org.postgresql:postgresql:42.7.4")
}
3.2. Минимальный класс
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class ConnectDemo {
public static void main(String[] args) throws Exception {
String url = "jdbc:postgresql://127.0.0.1:5432/angara_demo";
java.util.Properties props = new java.util.Properties();
props.setProperty("user", "angara");
props.setProperty("preferQueryMode", "simple");
try (Connection conn = DriverManager.getConnection(url, props)) {
conn.setAutoCommit(false);
try (PreparedStatement ps = conn.prepareStatement(
"INSERT INTO products (id, name, price) VALUES (?, ?, ?)")) {
ps.setLong(1, 4L);
ps.setString(2, "Cappuccino");
ps.setBigDecimal(3, new java.math.BigDecimal("4.75"));
ps.executeUpdate();
}
try (PreparedStatement ps = conn.prepareStatement(
"SELECT id, name, price FROM products ORDER BY id");
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
System.out.printf(
"%d %s %s%n",
rs.getLong("id"),
rs.getString("name"),
rs.getBigDecimal("price"));
}
}
conn.commit();
}
}
}
3.3. Что важно знать про JDBC-клиент
preferQueryMode=simple— рекомендованный default для AngaraBase. Это отключает агрессивный probe-режим extended-protocol, который драйвер использует для совместимости с PostgreSQL-расширениями. AngaraBase реализует pgwire по контракту, и часть extended-protocol-проверок не нужна.assumeMinServerVersion=9.0— добавьте вprops, если планируете работать через DBeaver/DataGrip; см. Совместимость клиентов → DBeaver.- Транзакции и
setAutoCommit(false). AngaraBase реализует MVCC через UNDO-log; явные транзакции дают предсказуемый snapshot. Не оставляйте долгие транзакции открытыми — это замедляет AngaraGC.
Дальше
- Обзор совместимости SQL — что именно из стандарта SQL доступно через все три клиента.
- Совместимость клиентов — справочник по конкретным GUI-инструментам и драйверам (DBeaver, IntelliJ DataGrip, и т.д.).
- Модель безопасности — как настроить TLS, SCRAM и аутентификацию по сертификату для production-подключений.
- Известные ограничения и SQLSTATE — какие коды клиент должен ожидать вместо «магических» значений.
Контракты в AngaraBase
Goal
Объяснить, что в AngaraBase понимается под словом «контракт», какие уровни контрактов существуют и какими механизмами они соблюдаются. Эта страница — для пользователей, DBA и новых контрибьюторов: чтобы при чтении документации, кода или сообщений об ошибках было понятно, на какие гарантии можно полагаться, а какие — явно вне контракта.
Что мы понимаем под контрактом
Контракт в AngaraBase — это явное обещание о наблюдаемом поведении компонента: что он принимает на вход, что возвращает, какие гарантии даёт и как ведёт себя при нарушении границ. Контракт не «лучшие намерения» и не «как обычно работает» — это формализованная договорённость, которую обязаны соблюдать обе стороны: реализация и вызывающий код (или клиент).
У контракта три ключевых свойства:
- Явность. Контракт зафиксирован в одном каноническом источнике — не в чате, не в коде комментария, не в «общем понимании команды».
- Проверяемость. Соблюдение контракта подтверждается автоматически: тестами, типами, метриками, lint-проверками.
- Fail-closed. При нарушении границы контракта система возвращает явную ошибку (с известным кодом), а не «как-нибудь продолжает работать».
Если что-то в системе не покрыто контрактом, это явно помечается как roadmap, experimental или known limitation. Поведение вне контракта может измениться без deprecation-цикла.
Уровни контрактов
В AngaraBase есть несколько уровней контрактов, каждый со своим источником истины и способом проверки.
1. SQL-контракт (внешний, для пользователя)
Что поддержано — поддержано полностью. Что не поддержано — возвращает явный SQLSTATE (0A000 feature_not_supported и др.), а не молчаливый bypass или искажённый результат.
- Источник: SQL — обзор совместимости, Известные ограничения и SQLSTATE.
- Проверка: pinned compat suite, регрессионные тесты на каждый зафиксированный SQLSTATE.
- Что это значит на практике: клиент может ловить
psycopg.errors.FeatureNotSupportedи точно знать, что попал в задокументированное ограничение, а не в баг.
2. Конфигурационный контракт
Каждый ключ конфига имеет тип, значение по умолчанию, диапазон допустимых значений и поведение при отсутствии или некорректном значении.
- Источник: Configuration, Configuration schema reference.
- Проверка: парсер отвергает неизвестные/некорректные ключи на старте (fail-closed), а не молча игнорирует.
- Изменение семантики ключа — через deprecation-цикл (см.
WRITING_RULES.md§9a).
3. Operational контракт
Метрики, USDT-зонды, имена sys.* view, формат backup/restore, формат логов и runbook-вывода — всё это
публичные имена, на которые завязан мониторинг и автоматизация оператора.
- Источник: System tables, Observability metrics checklist, Backup and restore, USDT/eBPF probes.
- Принцип: каждая ресурсная граница (RAM-бюджет буфер-пула, лимит write-set транзакции, snapshot age и т.д.) обязана иметь Prometheus-метрику и явное fail-closed поведение при нарушении. Граница без наблюдаемости — это не контракт.
4. Внутренние API-контракты (для контрибьютора)
Каждая подсистема ядра имеет публичный Rust-trait, который определяет её семантику: TableEngine,
PageProvider, TransactionLogSink, StorageIo и др. Без реализации контракта код не соберётся — это
«honest checked promise», а не «честное слово разработчика».
- Источник: doc-comments на trait-ах, Architecture overview, API Boundaries.
- Проверка: компилятор Rust + property-tests на инварианты + layering lint (
Coreне зависит отAdapters/Tooling).
5. Документационный контракт (anti-drift)
Документация — часть кода. Любое изменение публичного контракта (SQL surface, конфиг-ключи, метрики, SQLSTATE, имена сабсистем, защитные дефолты, порядок init/upgrade) обязательно сопровождается изменением AngaraBook в том же PR.
- Источник: WRITING_RULES.md §8 — Anti-drift contract.
- Проверка: pre-commit / CI прогоняют
tools/docs/lint_angarabook_public.py,tools/docs/check_public_build_security.pyи помечают расхождение как блокирующее.
Как мы соблюдаем контракты
Контракт без механизма соблюдения — декларация. В AngaraBase используется несколько слоёв принуждения, которые работают вместе.
Type system как первый рубеж
Result<T, Error>вместо panic.unwrap()/expect()в production-коде запрещены.- Bounded generics и trait-объекты вместо dynamic dispatch там, где инвариант можно зафиксировать на уровне типов.
- No-panic policy: сервер не падает из-за пользовательского ввода — он возвращает SQLSTATE.
Restrictive by default + fail-closed
Каждый компонент с ресурсной границей обязан определить:
- свою границу (например,
buffer_pool_size_mb,txn_max_write_set_mb,max_concurrent_queries), - поведение при её нарушении (явная ошибка с известным SQLSTATE),
- реакцию вызывающего кода (Reaction Propagation Contract).
Нет границы и нет fail-closed поведения — нет merge.
Pinned tests и golden datasets
Контракт SQL-совместимости и совместимости клиентов подтверждается pinned-тестами, а не «процентом совместимости». Если тест зафиксирован — изменение поведения требует либо обновления теста с обоснованием, либо отката изменения.
Подробнее: Testing and validation baseline, Golden dataset management, CI reproducibility contract.
Deprecation-цикл
Когда контракт выводится из обращения, он не исчезает молча. Применяется единый цикл: Active → Deprecated → Removed, минимум один major-релиз между объявлением Deprecated и Removed; до v1.0 — минимум две
minor-точки. Каждое изменение фазы — атомарный PR (код + AngaraBook + Migration steps).
Полный регламент: WRITING_RULES.md §9a — Deprecation policy. Public-список всех deprecated/removed контрактов: Известные ограничения и SQLSTATE.
Security gate как fail-closed для документации
Что это даёт пользователю
- Предсказуемость поведения. Если поведение задокументировано — оно стабильно в рамках мажора. Если задокументировано как ограничение со SQLSTATE — оно вернёт именно этот SQLSTATE, а не «иногда работает».
- Безопасный код клиента. Можно ловить конкретные SQLSTATE и строить логику ретраев / обработки ошибок без эвристик и парсинга текстовых сообщений.
- Понятный апгрейд. Изменение поведения публичного контракта проходит явный deprecation-цикл с migration-шагами; вы заранее видите, что и когда поменяется.
- Наблюдаемость гарантий. Каждая ресурсная граница имеет метрику; вы видите утилизацию и реджекты до того, как они станут инцидентом.
Что это даёт разработчику и контрибьютору
- Контракт компилятора, а не review-комментария. Если инвариант можно закодировать в trait или тип — он кодируется. Code review ловит то, что компилятор поймать не может.
- Один источник истины на тип знания. Не нужно «искать актуальную правду по нескольким документам»: для каждого слоя контракта есть один canonical owner.
- Предсказуемая работа с долгом. Deprecated-контракт фиксируется в
reference/known-issues.md, а если он не закрывается одним PR — в registry технического долга со статусомscheduled <target-train>. - Anti-drift в одном PR. Меняешь поведение — обновляешь AngaraBook здесь же. Не «доработать docs позже».
Что не является контрактом
Чтобы избежать ложных ожиданий, явно: контрактом не считаются:
- внутренние имена модулей, файлов и приватных функций ядра (могут меняться при рефакторинге без deprecation);
- поведение фич с frontmatter
status: experimentalили CLI-флагами--experimental-*— они никогда не считались стабильными; - тексты сообщений об ошибках (контракт —
SQLSTATEи его смысл, не текст); - не задокументированные побочные эффекты, замеченные эмпирически («у меня работает, если…»);
- бенчмарки и численные значения латентности — это observability, а не обещание производительности
(performance-claim требует pinned benchmark, см.
tools/perf_pack/).
Если вы опираетесь на что-то из этого списка в продакшене — это технический долг на стороне клиента, и очередное обновление AngaraBase его раскроет.
Links
- Project Principles §1 — Restrictive by Default — фундамент fail-closed подхода (см. также
docs/00_PROJECT_PRINCIPLES.mdв internal-сборке). - SQL — обзор совместимости — SQL-контракт.
- Известные ограничения и SQLSTATE — public-список границ и deprecated/removed контрактов.
- Configuration schema reference — конфигурационный контракт.
- Architecture overview, API Boundaries — внутренние API-контракты и layering.
- Observability metrics checklist — наблюдаемость как часть контракта.
- WRITING_RULES.md — документационный контракт (anti-drift, deprecation policy).
Хранение данных (Storage Engine)
Goal
Объяснить как AngaraBase хранит данные на диске, какие форматы файлов используются и какие движки хранения доступны (или запланированы).
Pluggable storage architecture
AngaraBase использует модульную архитектуру хранения: движок (storage engine) отвечает за физическое размещение данных, а верхние уровни (SQL, транзакции, индексы) работают через унифицированный интерфейс. Это позволяет подключать разные движки для разных workloads без изменения SQL-уровня.
Текущий движок — Row-Store (строковое хранилище). В будущем планируются Column-Store и In-Memory Engine.
Row-Store (текущий движок)
Page-based heap storage
Данные хранятся в страницах фиксированного размера (16 KB). Каждая таблица представлена набором heap-страниц, в которых строки размещаются последовательно.
Slotted pages
Каждая страница устроена как slotted page:
┌─────────────────────────────────────┐
│ Page Header (LSN, checksum, flags) │
├─────────────────────────────────────┤
│ Slot Array → [offset₁, offset₂…] │
│ (растёт вниз ↓) │
│ │
│ свободное место │
│ │
│ (данные строк растут вверх ↑) │
│ Row₂ data │ Row₁ data │
└─────────────────────────────────────┘
- Заголовок содержит LSN (log sequence number), контрольную сумму,
page_typeи флаги. - Slot array — массив указателей на строки внутри страницы. Это позволяет перемещать строки внутри
страницы без изменения внешних ссылок (TID =
page_id+slot_id). - Данные строк записываются от конца страницы к началу.
Типы страниц (page_type): 0 = data (heap), 1 = index (reserved), 2 = meta (reserved), 3 = overflow
(reserved).
Page checksums
Каждая страница защищена контрольной суммой (CRC32C). При чтении страницы с диска checksum проверяется; при несовпадении сервер возвращает ошибку и не выдаёт повреждённых данных (fail-closed with diagnostics).
Форматы файлов
AngaraBase использует per-database файловую модель: каждая база данных — это пара файлов.
| Расширение | Назначение | Magic |
|---|---|---|
.adb | Heap-страницы с данными таблиц и индексами. Самодостаточный per-database storage file. | APG1 |
.atl | Transaction log (WAL) для конкретной базы данных. Per-database WAL. | ADB1 |
Индексы AngaraTree хранятся внутри .adb файла — для них зарезервирован page_type = 1 в заголовке
страницы. Отдельного файла для индексов нет.
Source of truth: crates/angarabase/src/on_disk.rs, angarabook/src/operations/upgrade-and-migration.md.
Data directory layout
Каталог данных задаётся параметром storage.data_directory. Типичная структура:
data_directory/
├── VERSION # маркер инициализации (AVR1, 256 bytes, CRC32C)
├── base.adb # системная база данных (SysCatalog) — heap pages
├── base.atl # WAL системной базы данных
├── mydb.adb # пользовательская БД — heap pages + index pages
├── mydb.atl # WAL пользовательской БД
└── …
WAL не хранится в отдельных сегментированных файлах (как wal_000001 в PostgreSQL). В AngaraBase WAL —
это один файл .atl на каждую базу данных, размещённый в том же каталоге data_directory.
Параметр storage.transaction_log_directory задаёт альтернативный каталог для .atl файлов (полезно для
размещения WAL на отдельном диске).
Ключевые параметры
[storage]
data_directory = "/var/lib/angarabase/data"
transaction_log_directory = "/var/lib/angarabase/txlog"
Подробнее о параметрах — Конфигурация.
Column-Store (запланирован, v6)
Колоночный движок на основе Arrow/Parquet-like формата, ориентированный на аналитические запросы (OLAP). Данные хранятся по колонкам с поддержкой сжатия и vectorized scan.
Статус: не реализован, запланирован в roadmap v6.
In-Memory Engine (запланирован, v5 — AngaraMemory)
Движок для хранения данных в оперативной памяти. Запланированы три режима:
| Режим | Описание |
|---|---|
volatile | Данные только в памяти; теряются при перезапуске. |
logged | Записи дублируются в WAL; восстановление при перезапуске. |
snapshotted | Периодический snapshot на диск + WAL. |
Статус: в разработке.
HTAP direction
Долгосрочная стратегия AngaraBase — HTAP (Hybrid Transactional/Analytical Processing):
- Row-Store обслуживает OLTP (транзакционная нагрузка).
- Column-Store обслуживает OLAP (аналитика).
- Между ними — асинхронная репликация: данные из row-store преобразуются в колоночный формат для аналитических запросов.
Это позволит выполнять аналитику на свежих данных без ETL-конвейеров и без влияния на транзакционную производительность.
Связанные разделы
Концепции (что почитать дальше)
- Транзакции и MVCC — как версии страниц связаны с MVCC и WAL.
- Индексы — как B+tree-страницы укладываются поверх tablespace.
- Каталог и метаданные — где physical-метаданные таблиц видны из SQL.
How-to (что сделать)
- Конфигурация — настройки
storage,wal,checkpoint. - Резервное копирование и восстановление — как переносить datadir между инстансами.
- Crash recovery — поведение storage после аварийного завершения.
- Диагностика — как смотреть IO/page-cache метрики.
Справочник
- Системные представления
sys.*—sys.tablespaces,sys.healthдля интроспекции состояния хранилища. - Известные ограничения и SQLSTATE — раздел
STORAGE_*ошибок.
Транзакции и MVCC
AngaraBase обеспечивает конкурентный доступ к данным через MVCC (Multi-Version Concurrency Control). Транзакции гарантируют атомарность изменений, а MVCC позволяет читателям и писателям работать одновременно без взаимных блокировок.
Основы транзакций
Управление транзакциями
BEGIN; -- начать явную транзакцию
SAVEPOINT sp1; -- создать точку сохранения
ROLLBACK TO SAVEPOINT sp1; -- откатить до точки сохранения
COMMIT; -- зафиксировать транзакцию
ROLLBACK; -- откатить всю транзакцию
Autocommit
По умолчанию AngaraBase работает в режиме autocommit: каждый отдельный SQL-оператор выполняется как самостоятельная транзакция. Если оператор завершается успешно — результат фиксируется автоматически, при ошибке — откатывается.
Для операций, затрагивающих несколько строк или таблиц, используйте явные транзакции (BEGIN / COMMIT),
чтобы объединить изменения в единую атомарную единицу.
MVCC: версионирование строк
Ключевая идея MVCC — читатели не блокируют писателей, писатели не блокируют читателей. Это достигается за счёт хранения нескольких версий каждой строки.
Метаданные версий
Каждая версия строки содержит два служебных поля:
| Поле | Назначение |
|---|---|
created_commit | Epoch (commit timestamp), при котором версия была создана |
deleted_commit | Epoch, при котором версия была помечена как удалённая (∞ для активных версий) |
Правило видимости
Версия строки видна транзакции со snapshot S, если выполняются оба условия:
created_commit <= S— версия создана до или в момент snapshot- Версия не удалена, или
deleted_commit > S— удаление произошло после snapshot
Операции записи
- INSERT — создаёт новую версию строки с
created_commit= текущий epoch - UPDATE — не меняет строку на месте. Вместо этого: помечает текущую версию как удалённую
(
deleted_commit= текущий epoch) и создаёт новую версию с обновлёнными данными - DELETE — помечает версию как удалённую (
deleted_commit= текущий epoch)
Уровни изоляции
Каждая транзакция получает snapshot — фиксированное представление данных на определённый момент времени.
READ COMMITTED (по умолчанию)
Snapshot обновляется перед каждым оператором. Транзакция видит все данные, зафиксированные до начала текущего оператора. Это рекомендуемый уровень изоляции для большинства задач.
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
REPEATABLE READ
Snapshot фиксируется в момент BEGIN и не меняется до конца транзакции. Все операторы внутри транзакции видят одно и то же состояние данных.
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SERIALIZABLE
С версии 0.6.4.4 AngaraBase реализует полноценный SERIALIZABLE (SSI) уровень изоляции.
В режиме SERIALIZABLE аномалии write skew и phantoms предотвращаются через
механизм SIREAD-блокировок и отслеживание rw-антизависимостей.
Транзакции, нарушающие сериализуемость, прерываются с кодом 40001.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Блокировки
Операции чтения
Чтение использует MVCC snapshot и не требует блокировок. Читатель никогда не ждёт писателя и наоборот.
Операции записи (Lock-Free DML)
Писатели используют атомарные операции (Compare-And-Swap) для установки версий на уровне строк, что обеспечивает lock-free бесконфликтные изменения. Блокировки в классическом виде больше не удерживаются.
DDL-операции
Операции изменения схемы (CREATE TABLE, ALTER TABLE, DROP TABLE) захватывают table-level locks на время выполнения.
Обнаружение deadlock
AngaraBase обнаруживает взаимные блокировки (deadlock) с помощью:
- Timeout — если транзакция ожидает блокировку дольше заданного порога, она прерывается
- Victim selection — при обнаружении цикла система выбирает транзакцию-жертву для отката
- Deterministic lock ordering — внутренняя стратегия упорядочивания блокировок для снижения вероятности deadlock
Сборка мусора (AngaraGC)
Со временем в хранилище накапливаются старые версии строк, которые больше не видны ни одной активной транзакции. Подсистема AngaraGC отвечает за их очистку.
Механизм работы
- GC watermark — вычисляется как минимальный snapshot среди всех активных транзакций:
min(active_snapshots) - Версии строк с
deleted_commit < watermarkбезопасны для удаления — ни одна активная транзакция не может их увидеть - Очистка выполняется фоновым процессом без остановки обработки запросов
- Bounded slices — GC обрабатывает данные порциями фиксированного размера, чтобы не вызывать всплески задержки
- Epoch Reaper — фоновый процесс (начиная с версии 0.6.5.24), который предотвращает зависание GC watermark из-за разорванных соединений или зависших сессий.
Отличие от PostgreSQL
В AngaraBase нет autovacuum в привычном понимании. Используется гибридный дизайн с epoch-based watermark (как в Oracle/InnoDB), что позволяет точнее контролировать момент очистки.
Рекомендации
- Используйте READ COMMITTED (уровень по умолчанию) для большинства рабочих нагрузок
- Избегайте долгоживущих транзакций — они удерживают GC watermark и не позволяют очистить старые версии строк, что увеличивает потребление дискового пространства
- При использовании REPEATABLE READ помните о возможности write skew. Если нужна строгая сериализуемость,
используйте явные блокировки (
SELECT ... FOR UPDATE)
MVCC state при crash recovery
При перезапуске после аварийного завершения AngaraBase восстанавливает состояние MVCC из transaction log (WAL).
Что восстанавливается
- Committed transactions — транзакции, которые успели записать COMMIT в WAL
- Aborted transactions — незавершённые транзакции помечаются как aborted
- MVCC visibility — информация о том, какие версии строк видны для каждого commit epoch
- Transaction counters — текущий commit epoch и другие счётчики
Процесс восстановления
- WAL scan — сканирование файлов transaction log в хронологическом порядке
- MVCC replay — восстановление in-memory структур MVCC из записей в WAL
- Cleanup — пометка незавершённых транзакций как aborted
Ограничения
- Backend requirement: восстановление MVCC работает только с
transaction_log.backend = "file_bin" - Memory rebuild: MVCC state восстанавливается в памяти, что может занять время при большом объёме WAL
- Read-your-writes: сразу после restart незавершённые транзакции не видны (помечены как aborted)
Мониторинг восстановления
-- Проверить режим восстановления
SELECT recovery_mode FROM sys.identity;
-- Проверить состояние системы после recovery
SELECT txn_commit_epoch_current FROM sys.health;
Возможные значения recovery_mode:
"normal"— обычный старт без восстановления"crash_recovery"— восстановление после аварийного завершения"forced_takeover"— принудительный захват instance lease
Связанные разделы
- Storage engine — устройство хранилища и формат страниц
- Instance Lifecycle — жизненный цикл инстанса и crash recovery
- Crash Recovery — операционные процедуры восстановления
- Справочник SQL — синтаксис SQL-операторов
Индексы (Indexes)
Goal
Объяснить какие типы индексов доступны в AngaraBase, когда их использовать и как они взаимодействуют с MVCC.
AngaraTree — index engine
AngaraTree — индексный движок AngaraBase. Индексы хранятся в .atl-файлах отдельно от heap-данных.
B+tree (default)
Основной тип индекса. Подходит для equality- и range-запросов; ключи хранятся в детерминированном порядке.
-- Создание B+tree индекса (эквивалентные формы):
CREATE INDEX idx_name ON orders (customer_id);
CREATE INDEX idx_name ON orders USING btree (customer_id);
B+tree индекс ускоряет:
- Точные совпадения:
WHERE customer_id = 42 - Диапазоны:
WHERE created_at >= '2026-01-01' AND created_at < '2026-02-01' - Сортировку:
ORDER BY customer_id
BRIN (Block Range Index)
Компактный индекс для данных с естественным порядком (append-only, time-series). BRIN хранит min/max значения для диапазонов heap-страниц, что позволяет пропускать целые блоки при сканировании.
CREATE INDEX idx_ts ON events USING brin (created_at);
Поддерживаемые типы ключей:
| Тип | Алиасы |
|---|---|
INTEGER | int, int4 |
BIGINT | int8 |
DATE | — |
TIMESTAMP | — |
TIMESTAMPTZ | — |
Как BRIN работает: индекс выступает как accelerator path — сначала отсекаются блоки, не содержащие нужных значений, затем выполняется heap fetch с MVCC predicate recheck. BRIN не гарантирует точность — он только сужает область поиска.
Метрика эффективности: angara_brin_range_efficiency показывает долю блоков, пропущенных благодаря BRIN.
Чем ближе к 1.0, тем эффективнее индекс (данные хорошо кластеризованы).
Hash / Bloom
Зарезервированы как optional/future index types. На данный момент не реализованы.
Индексы и MVCC
Индекс хранит ссылки TID (page_id, slot_id) на строки в heap. Видимость строки определяется не
индексом, а MVCC-слоем при чтении heap-страницы:
- Запрос обращается к индексу → получает набор TID.
- По каждому TID читается heap-страница.
- MVCC-слой проверяет видимость версии строки для текущей транзакции.
Следствие: индекс может содержать ссылки на невидимые (устаревшие) версии строк. Это нормально — такие записи фильтруются при heap fetch.
IndexStore — персистентные вторичные индексы
AngaraBase поддерживает персистентные вторичные индексы для RowStore таблиц через IndexStore.
Как работает
CREATE INDEXстроит индекс через полный скан таблицы (build_from_rows) и сохраняет результат.- DML (INSERT/DELETE) автоматически обновляет все индексы таблицы — fail-closed: если обновление индекса не удалось, heap mutation откатывается.
- Оптимизатор использует индекс для
WHERE col = valueзапросов (O(log N) вместо O(N) seq_scan).
Ресурсные ограничения
| Ограничение | Конфиг | При нарушении |
|---|---|---|
| Макс. страниц на индекс | storage.max_index_pages_per_table | PageLimitExceeded → DML abort |
| Время обслуживания индекса | storage.index_maintenance_budget_ms (default: 5000ms) | MaintenanceBudgetExceeded → DML abort |
Наблюдаемость
| Метрика | Описание |
|---|---|
angarabase_index_inserts_total | Всего вставок в индекс |
angarabase_index_deletes_total | Всего удалений из индекса |
angarabase_index_reject_total | Отклонённые DML из-за ошибок индекса |
angarabase_index_maintenance_duration_ms | Гистограмма времени обслуживания индекса |
Текущие ограничения
| Ограничение | Статус |
|---|---|
| Только single-column индексы | Текущая версия (v0 bound) |
| Нет partial indexes | Не поддержано (v4 scope) |
| Нет expression indexes | Не поддержано (v4 scope) |
| Нет covering indexes | Не поддержано (v4 scope) |
| Online index build (без блокировки DML) | Не поддержано (H1-v0.7.x) |
| WAL-first для index mutations | In-memory index: восстанавливается через build_from_rows при recovery. Disk-backed WAL-first — в roadmap дальнейших релизов. |
Попытка создать неподдерживаемый индекс возвращает SQLSTATE 0A000 (feature_not_supported).
Когда создавать индексы
Рекомендуется:
- На колонках, часто используемых в
WHERE,JOIN ON,ORDER BY. - BRIN — на time-series колонках таблиц с
append_only = true, где данные вставляются в порядке возрастания ключа.
Не рекомендуется:
- На таблицах с малым количеством строк (full scan будет быстрее).
- На колонках с очень низкой селективностью (например,
boolean-флаги). - Создание множества индексов на одной таблице замедляет
INSERT/UPDATE/DELETE.
Используйте EXPLAIN ANALYZE для проверки, использует ли оптимизатор индекс. Подробнее — Обработка
запросов.
Проверка целостности индекса
Для offline-проверки целостности B+tree индекса доступна функция validate():
SELECT angara_index_validate('idx_name');
Рекомендуется выполнять после аварийного завершения или восстановления из backup.
Связанные разделы
Концепции (что почитать дальше)
- Обработка запросов — как оптимизатор выбирает и комбинирует индексы.
- Хранение данных — как страницы B+tree ложатся в tablespace.
- Транзакции и MVCC — почему обновление индексов под нагрузкой требует MVCC-видимости.
How-to (что сделать)
- DDL: CREATE/DROP INDEX — синтаксис создания и удаления индексов.
- Диагностика — как через
EXPLAIN ANALYZEиsys.*понять, используется ли индекс.
Справочник
- Типы данных — какие типы поддерживаются как ключи индексов.
- Системные представления
sys.*—sys.indexes,sys.column_statsдля анализа покрытия.
Обработка запросов (Query Processing)
Goal
Объяснить как AngaraBase обрабатывает SQL-запросы: от текста до результата. Полезно для понимания
EXPLAIN-планов и диагностики производительности.
Pipeline overview
Каждый SQL-запрос проходит четыре стадии:
SQL text ──▸ Parsing ──▸ Planning ──▸ Optimization ──▸ Execution ──▸ Result
1. Parsing: SQL → AST
Парсер преобразует текст запроса в абстрактное синтаксическое дерево (AST). AngaraBase использует PostgreSQL-совместимый SQL-диалект.
Если синтаксис не поддерживается, сервер возвращает SQLSTATE 0A000 (feature_not_supported) с описанием
неподдерживаемой конструкции.
2. Planning: AST → logical plan
На этапе планирования выполняется:
- Name resolution — сопоставление имён таблиц, колонок и функций с объектами каталога.
- Type checking — проверка типов и автоматическое приведение (coercion) при необходимости.
Результат — логический план, описывающий что нужно сделать, но не как.
3. Optimization (AngaraPlan)
Оптимизатор AngaraPlan преобразует логический план в физический, выбирая наиболее эффективную стратегию выполнения.
Cost-based optimizer (CBO): решения принимаются на основе статистики (AngaraStat) — количество строк, распределение значений, наличие индексов.
Ключевые решения оптимизатора:
| Решение | Варианты |
|---|---|
| Access path | Full table scan, B+tree index scan, BRIN scan |
| Join method | Hash join, nested loop join |
| Join order | Перестановка таблиц для минимизации промежуточных результатов |
Robust planning: оптимизатор устойчив к ошибкам в оценках — при значительном расхождении между estimated и actual rows план остаётся работоспособным (не приводит к worst-case поведению).
LEO (Learning Optimizer): feedback loop — после выполнения запроса фактическая статистика используется для улучшения будущих оценок.
4. Execution (AngaraFlow)
Исполнитель AngaraFlow выполняет физический план в iterator/streaming модели (Volcano): каждый оператор запрашивает следующую строку у дочернего оператора.
Основные операторы:
| Оператор | Описание |
|---|---|
| Scan | Чтение строк из heap (full scan) или индекса (index scan) |
| Filter | Применение предикатов WHERE |
| Hash Join | Соединение через hash-таблицу; Grace hash join для больших datasets |
| Nested Loop | Соединение вложенными циклами (для малых таблиц или index lookup) |
| Group By | Агрегация (GROUP BY, HAVING) |
| Sort | Сортировка; external sort для данных, не помещающихся в память |
| Limit | Ограничение количества строк |
AngaraStat (статистика)
Оптимизатор использует статистику из системных таблиц для оценки стоимости планов.
sys.table_stats
| Колонка | Описание |
|---|---|
row_count | Оценочное количество строк в таблице |
mutation_epoch | Счётчик мутаций (для определения устаревшей статистики) |
sys.column_stats
| Колонка | Описание |
|---|---|
ndv | Number of distinct values (HyperLogLog) |
min_value / max_value | Границы диапазона значений |
null_count | Количество NULL-значений |
histogram | Распределение значений (equi-height histogram) |
mcv | Most common values (частые значения и их доли) |
Управление уровнем статистики
ALTER TABLE t SET (stats_level_max = 2);
| Level | Что собирается |
|---|---|
| 0 | Только row_count и mutation_epoch |
| 1 | + NDV, min/max, null_count |
| 2 | + Histograms, MCV (reservoir sampling) |
| 3 | + Extended statistics (зарезервировано) |
Более высокий уровень даёт оптимизатору больше информации, но увеличивает время сбора статистики.
Диагностика запросов
EXPLAIN
Просмотр плана выполнения без выполнения запроса:
EXPLAIN SELECT * FROM orders WHERE customer_id = 42;
Варианты:
EXPLAIN ANALYZE SELECT ...; -- выполняет запрос, показывает actual rows/time
EXPLAIN (BUFFERS) SELECT ...; -- + статистика чтения страниц
EXPLAIN (FORMAT JSON) SELECT ...; -- вывод в JSON
Системные представления
| Представление | Описание |
|---|---|
angara_stat_activity | Текущие активные запросы |
angara_stat_statements | Агрегированная статистика по типам запросов |
angara_top_queries | Топ-запросы по времени выполнения |
Slow query log
Включается через переменную окружения:
ANGARABASE_LOG_MIN_DURATION_MS=100 # логировать запросы дольше 100 мс
ANGARABASE_LOG_QUERY_TEXT=1 # включить текст запроса в лог
Подробнее — Диагностика.
Future
Запланированные улучшения обработки запросов:
| Компонент | Описание |
|---|---|
| AngaraVector | Vectorized/SIMD execution — обработка batch по колонкам вместо row-at-a-time |
| AngaraParallel | Morsel-driven parallelism — параллельное выполнение на нескольких ядрах |
| AngaraAdapt | Adaptive processing — переключение стратегий во время выполнения |
Связанные разделы
Концепции (что почитать дальше)
- Индексы — как оптимизатор выбирает индекс для
SELECT/UPDATE. - Каталог и метаданные — где хранится статистика, которой пользуется планировщик.
- Транзакции и MVCC — как уровень изоляции влияет на план выполнения.
How-to (что сделать)
- Диагностика —
EXPLAIN ANALYZE, slow-query log, как читать план. - Tracing — распределённая трассировка фаз parse → plan → execute.
- Логирование —
ANGARABASE_LOG_QUERY_TEXT,ANGARABASE_LOG_MIN_DURATION_MS.
Справочник
- SQL Overview — что из стандарта поддерживается на уровне planner-а.
- Системные представления
sys.*—sys.queries,sys.column_stats,sys.health.
Системный каталог и метаданные
AngaraBase хранит метаданные всех объектов базы данных в центральном реестре — SysCatalog. Для
пользователей доступ к метаданным предоставляется через системные представления sys.* и функции
интроспекции.
Иерархия объектов
Объекты базы данных организованы в строгую иерархию:
Instance → Database → Schema → Table → Column
Каждый уровень имеет уникальный идентификатор в SysCatalog. Таблицы принадлежат схемам, схемы — базам данных, базы данных — экземпляру (instance).
SysCatalog
SysCatalog — центральный реестр метаданных. Он хранит информацию о:
- таблицах, колонках и их типах данных
- индексах и ограничениях (constraints)
- пользователях, ролях и привилегиях
- функциях и агрегатах
- политиках безопасности (RLS)
- статистике для оптимизатора запросов
SysCatalog обновляется при DDL-операциях (CREATE, ALTER, DROP) и при сборе статистики.
Системные представления (sys.*)
Системные представления доступны только для чтения и не требуют специальных привилегий (за исключением представлений, связанных с безопасностью).
Идентификация и состояние экземпляра
| Представление | Описание |
|---|---|
sys.identity | Идентификация экземпляра: версия, instance_id |
sys.health | Состояние здоровья сервера |
sys.settings | Эффективная конфигурация (name, value). Секреты не раскрываются |
Структура данных
| Представление | Описание |
|---|---|
sys.tables | Все таблицы с метаданными (schema, имя, тип, row count) |
sys.columns | Колонки каждой таблицы: column_name, data_type, nullable и т.д. |
Статистика
| Представление | Описание |
|---|---|
sys.table_stats | Статистика на уровне таблицы: stats_level_max, last_committed_rowid, mutation epochs |
sys.column_stats | Статистика по колонкам: ndv_approx, min/max, null_count, гистограммы, MCV |
Безопасность и доступ
| Представление | Описание |
|---|---|
sys.users | Учётные записи пользователей |
sys.roles | Роли |
sys.user_roles | Назначения пользователей ролям |
sys.role_privileges | Привилегии ролей |
sys.object_grants | Гранты на уровне объектов |
sys.my_privileges | Привилегии текущего пользователя |
sys.security_policies | Политики RLS |
sys.audit_log | Журнал аудита |
Функции интроспекции
AngaraBase предоставляет набор встроенных функций для программного доступа к метаданным.
Роли и привилегии
| Функция | Назначение |
|---|---|
angara_user_roles() | Роли текущего пользователя |
angara_role_privileges() | Привилегии заданной роли |
angara_user_privileges() | Эффективные привилегии пользователя |
angara_object_privileges() | Привилегии на конкретный объект |
angara_has_privilege() | Проверка наличия конкретной привилегии |
Безопасность (RLS, audit, break-glass)
| Функция | Назначение |
|---|---|
angara_table_policies() | RLS-политики для таблицы |
angara_is_rls_active() | Активна ли RLS для таблицы |
angara_effective_rls_predicate() | Итоговый предикат RLS для текущего пользователя |
angara_break_glass_status() | Статус break-glass сессии |
angara_audit_verify_chain() | Проверка целостности цепочки аудита |
Диагностика и производительность
| Функция / представление | Назначение |
|---|---|
angara_stat_activity | Активные сессии и выполняемые запросы |
angara_stat_statements | Агрегированная статистика выполненных запросов |
angara_top_queries() | Топ запросов по потреблению ресурсов |
angara_stat_statements_reset() | Сброс статистики запросов |
Практические примеры
Информация об экземпляре
SELECT * FROM sys.identity;
Проверка состояния сервера
SELECT * FROM sys.health;
Список всех таблиц
SELECT * FROM sys.tables;
Проверка настроек безопасности
SELECT name, value FROM sys.settings WHERE name LIKE 'security.%';
Просмотр статистики по колонкам таблицы
SELECT column_name, ndv_approx, null_count
FROM sys.column_stats
WHERE table_name = 'orders';
Проверка привилегий текущего пользователя
SELECT * FROM sys.my_privileges;
SELECT angara_has_privilege('orders', 'SELECT');
Связанные разделы
- Quickstart (примеры sys.*) — первые шаги с системными представлениями
- Безопасность — функции интроспекции безопасности
- Диагностика — мониторинг и устранение проблем
- Обработка запросов — как оптимизатор использует метаданные каталога
Instance Lifecycle
This document explains the conceptual model of AngaraBase instance identity, lifecycle, and the Instance Lease system that enables safe crash recovery and storage portability.
Instance Identity
Each AngaraBase instance has a unique identity established during initialization:
Core Identity Components
cluster_id: UUID identifying the logical database clusterinstance_id: UUID identifying this specific instance- Data directory: Physical location of database files
- Transaction log directory: Physical location of WAL files
Identity Persistence
Identity is stored in two places:
- VERSION marker: Binary file with format version and IDs
- System catalog pages: In
base.adbreserved pages with full metadata
Instance Lease System
The Instance Lease prevents multiple instances from accessing the same data files simultaneously, which would cause corruption.
Lease Structure
#![allow(unused)]
fn main() {
pub struct InstanceLeaseV0 {
pub holder_id: String, // UUID of owning instance
pub acquired_at_unix_s: u64, // When lease was taken
pub expires_at_unix_s: u64, // When lease expires (TTL)
pub holder_pid: u32, // Process ID (diagnostic)
pub holder_hostname: String, // Hostname (diagnostic)
}
}
Lease State Machine
[None] ──acquire──> [Held] ──heartbeat──> [Held]
↑ │ │
│ │ │
└──expired/release──┘ │
│
[Expired] <──────────timeout─────────────────┘
│
└──takeover──> [Held by new instance]
State Transitions
- None → Held: First instance startup or after graceful shutdown
- Held → Held: Periodic heartbeat updates (every 10s by default)
- Held → None: Graceful shutdown releases lease immediately
- Held → Expired: Heartbeat stops (crash, network partition)
- Expired → Held: New instance takes over after TTL expiration
Lease Storage
- Location: Stored in
SysCatalogMetaV0withinbase.adbpages - Persistence: Atomic updates with full page images
- Reliability: Works on NFS/SAN where
flock()is unreliable
Startup Sequence
Phase 1: Pre-flight Checks
- Verify data directory exists and is initialized
- Check VERSION marker compatibility
- Validate page size matches compiled binary
Phase 2: Lease Acquisition
- Load system catalog from
base.adb - Check existing lease status:
- No lease: Acquire immediately
- Expired lease: Take over with warning
- Active lease: Fail with informative error
- Force takeover: Override active lease (dangerous)
Phase 3: Recovery
- WAL Recovery: Replay transaction log (file_bin backend)
- MVCC Recovery: Restore in-memory transaction state
- Heartbeat Start: Begin periodic lease renewal
Phase 4: Ready for Connections
- Start protocol listeners (pgwire, admin)
- Begin accepting client connections
- Continue heartbeat until shutdown
Recovery Modes
AngaraBase tracks the recovery mode for operational visibility:
Normal Startup
- Clean start on existing, properly shut down data
- No WAL replay required
recovery_mode = "normal"
Crash Recovery
- Previous instance terminated unexpectedly
- WAL replay recovers committed transactions
- MVCC state rebuilt from transaction log
recovery_mode = "crash_recovery"
Forced Takeover
- Operator used
ANGARABASE_FORCE_LEASE_TAKEOVER=1 - May indicate emergency recovery scenario
recovery_mode = "forced_takeover"
Shared Storage Scenarios
The Instance Lease system enables AngaraBase to work correctly on shared storage where multiple hosts can access the same files.
NFS/SAN Deployment
Host A ──┐
├── NFS/SAN ──> [data/] [txlog/]
Host B ──┘ [base.adb with lease]
Benefits
- Failover: Host B can take over if Host A crashes
- Maintenance: Move instance between hosts without dump/restore
- Testing: Run against production data copies safely
Limitations
- Single writer: Only one instance can write at a time
- Network partitions: May cause false lease expiration
- Performance: Network storage latency affects throughput
File Copy Scenarios
For non-shared storage, manual file copy enables:
- Backup testing: Verify backup integrity on different host
- Development: Use production data copy for debugging
- Migration: Move to new hardware without downtime
Configuration
Lease Timing
ANGARABASE_LEASE_TTL_S: How long lease lasts (default: 30s)ANGARABASE_LEASE_HEARTBEAT_S: Renewal frequency (default: 10s)
Safety Controls
ANGARABASE_FORCE_LEASE_TAKEOVER: Emergency override (default: false)
Recommended Settings
# Production: Longer TTL for network stability
export ANGARABASE_LEASE_TTL_S=60
export ANGARABASE_LEASE_HEARTBEAT_S=20
# Development: Shorter TTL for faster iteration
export ANGARABASE_LEASE_TTL_S=15
export ANGARABASE_LEASE_HEARTBEAT_S=5
Monitoring and Observability
Instance Status
-- Check current lease holder
SELECT lease_holder_id, lease_holder_hostname,
lease_expires_at, recovery_mode
FROM sys.identity;
-- Check system health
SELECT uptime_seconds, txn_commit_epoch_current
FROM sys.health;
Lease Events
AngaraBase logs lease events to stderr:
Instance lease acquired: holder=abc123...
Instance lease taken over: holder=def456...
Warning: lease heartbeat failed: I/O error
Instance lease released: holder=abc123...
Metrics Integration
Future versions will expose lease metrics via:
- Prometheus metrics endpoint
sys.metricsvirtual table- Structured logging output
Security Considerations
Access Control
- Lease system does NOT provide authentication
- File system permissions still required
- Network access controls recommended for shared storage
Audit Trail
- Lease changes logged with timestamps
- Instance identity tracked in
sys.identity - Recovery mode visible for forensics
Troubleshooting
Common Issues
“Cannot start: database files are owned by another instance”
- Diagnosis: Active lease prevents startup
- Resolution: Wait for expiration or verify other instance is dead
Frequent lease takeovers
- Diagnosis: Network instability or resource contention
- Resolution: Increase TTL, check network/disk performance
“MVCC recovery failed”
- Diagnosis: Corrupted transaction log
- Resolution: Check filesystem, restore from backup if needed
Debug Information
-- Instance identity and lease
SELECT * FROM sys.identity;
-- Recent recovery statistics
SELECT * FROM sys.health;
-- Transaction log status
SELECT * FROM sys.settings WHERE name LIKE 'transaction_log.%';
Связанные разделы
Концепции (что почитать дальше)
- Хранение данных — datadir, который защищает instance lease.
- Транзакции и MVCC — что происходит с активными транзакциями при
forced_takeover.
How-to (что сделать)
- Crash recovery — операционные процедуры восстановления после аварийного завершения.
- Конфигурация — переменные
instance_lease.*,recovery.*. - Резервное копирование и восстановление — как защитить datadir и снять снапшот.
Справочник
- Системные представления
sys.*—sys.identity,sys.healthдля диагностики lease-стейта. - Известные ограничения и SQLSTATE — раздел
INSTANCE_*ошибок.
SQL compatibility overview
Goal
Понять модель совместимости AngaraBase с PostgreSQL и быстро интерпретировать ошибки при тестировании.
Approach
AngaraBase реализует ограниченное подмножество PostgreSQL SQL через pgwire-протокол.
Неподдерживаемые конструкции возвращают явный SQLSTATE (чаще всего 0A000 feature_not_supported), а не
молчаливый некорректный результат.
Принцип: fail-closed — если feature не реализован, клиент получает детерминированную ошибку.
Source of truth
| Источник | Путь |
|---|---|
| Known issues (canonical) | angarabook/src/operations/known-issues.md |
| Compat probes (tests) | tools/compat_suite/run.sh |
| User-facing known issues | Known issues |
Practical advice
- ORM/tooling (DBeaver, psql, Hibernate и др.) часто выполняют
pg_catalogзапросы при подключении. Ориентируйтесь на результаты compat suite режимов--dbeaver-smoke/--nightly. - Если вы наблюдаете hang/stall — это P0/P1 bug. Соберите артефакты по инструкции в Support.
SQLSTATE quick reference
| SQLSTATE | Name | Typical scenario |
|---|---|---|
0A000 | feature_not_supported | WITH RECURSIVE, complex RLS predicates, multi-column ON CONFLICT target, ON CONFLICT ON CONSTRAINT |
23514 | check_violation | Partition routing: no matching partition and no DEFAULT |
42809 | wrong_object_type | UPDATE/DELETE on append-only table; PK/FK update under no_delete |
22023 | invalid_parameter_value | Invalid stats_level_max, invalid break-glass TTL, setval value out of [MINVALUE..MAXVALUE] |
42501 | insufficient_privilege | Missing roles for security operations, no SecurityContext |
25001 | active_sql_transaction | SET SESSION CONTEXT inside an active transaction |
2200H | sequence_generator_limit_exceeded | nextval past MAXVALUE/MINVALUE without CYCLE (RM-0.6.3.7) |
55000 | object_not_in_prerequisite_state | currval(seq) before any nextval in the current session (RM-0.6.3.7, session-bound contract) |
42P07 | duplicate_object | CREATE SEQUENCE of an existing name without IF NOT EXISTS |
42P01 | undefined_table | DROP SEQUENCE / nextval / currval / setval on a missing sequence |
428C9 | generated_always | INSERT with explicit non-NULL into a GENERATED ALWAYS AS IDENTITY column |
Полный список с контекстом: Known issues.
SQL reference pages
Текущий статус подсистем SQL на ветке 0.6.x. Бэйджи отражают, насколько подсистема покрыта pinned-тестами
compat-suite и можно ли на неё опираться в production-сценариях.
| Тема | Страница | Статус |
|---|---|---|
| Типы данных | data-types.md | Stable |
| DDL (CREATE, ALTER, DROP) | ddl.md | Stable |
| DML (INSERT, UPDATE, DELETE) | dml.md | Stable |
| Запросы (CTE, JOIN, ORDER BY) | queries.md | Stable |
| Секционирование таблиц | partitioning.md | Baseline |
SQL Functions (RM-0.6.5.5)
AngaraBase implements a subset of PostgreSQL built-in functions.
| Function | Signature | Description |
|---|---|---|
NOW() | () → timestamp | Current UTC time |
CURRENT_TIMESTAMP | () → timestamp | Alias for NOW() |
date_trunc(field, ts) | (text, timestamp) → timestamp | Truncate timestamp to field. Supported fields: microseconds, milliseconds, second, minute, hour, day, week, month, quarter, year, decade, century, millennium. Unknown field returns NULL. |
set_config(name, val, local) | (text, text, bool) → text | Stub: returns val. Used for Django compatibility. |
obj_description(oid, cat) | (oid, text) → text | Stub: returns NULL. Used for Django introspection. |
Vector execution visibility
When vector execution mode allows vector path (ANGARABASE_SQL_EXECUTION_MODE=auto for supported plans, or
force_vector), EXPLAIN surfaces vector operator names:
VectorSeqScanVectorFilterVectorProjectVectorHashJoinVectorAgg
If the plan shape is not supported by AngaraVector, planner/executor keeps row operators in EXPLAIN.
Execution mode behavior:
auto(default) — Stable use vector only for fully supported plan shapes, otherwise deterministic row fallback.force_row— Stable always use row executor.force_vector— Experimental fail-closed withfeature_not_supportedif vector execution is not possible. Подходит для целевого тестирования векторного пути; не рекомендуется для production-нагрузки в0.6.x.
AngaraMemory table options
CREATE TABLE ... WITH (...) now supports bounded memory-table surfaces:
storage='memory'— Baseline selects AngaraMemory table engine.durability='none'|'logged'|'snapshotted'— Baseline volatile/durable behavior.max_rows=<n>— Stable hard row-cap; overflow is fail-closed (54023).eviction_policy='error'|'fifo'— Experimental defaulterror;fifois opt-in.checkpoint_interval_ms=<n>— Baseline valid only withdurability='snapshotted'.
If max_rows is omitted for memory tables, bounded default is applied from instance policy.
Behavior clarification for durability='snapshotted':
- DML hot path does not perform immediate page persistence.
- Checkpoint worker applies per-table scheduling using each table’s
checkpoint_interval_ms(with bounded fallback).
Links
- Known issues: Known issues
- Support: Support
- Security model: Security / authorization
Data types
Goal
Справочник поддерживаемых типов данных AngaraBase и правила приведения типов.
Supported types
| SQL type | Alias | Storage | Notes |
|---|---|---|---|
INTEGER | INT, INT4 | 32-bit signed | Primary numeric type |
BIGINT | INT8 | 64-bit signed | Large counters, IDs |
VARCHAR(n) | — | Variable-length text | Bounded by n characters |
TEXT | — | Variable-length text | Unbounded text |
BOOLEAN | BOOL | 1-byte | TRUE / FALSE / NULL (OID 16) |
TIMESTAMP | — | Text-backed compat | ISO 8601 UTC (OID 1114) |
DATE | — | Text-backed compat | ISO 8601 date portion (OID 1082) |
Text-backed temporal types
TIMESTAMP и DATE хранятся в text-backed compatibility mode. Это означает:
- Сравнения выполняются как текстовые (лексикографические); ISO 8601 формат гарантирует корректный порядок.
- Serialization (RM-0.6.5.5):
TIMESTAMPвсегда сериализуется в UTC без смещения (например,2026-05-07 14:30:00.123). Трейлинг-нули микросекунд обрезаются. - Арифметика (
INTERVALи пр.) не поддерживается —0A000. - BRIN-индексы на
date/timestamp/timestamptzколонках поддерживаются (используют текстовые min/max).
Planned types
| SQL type | Status |
|---|---|
DECIMAL / NUMERIC | Planned |
UUID | Planned |
Попытка использовать неподдерживаемый тип приведёт к ошибке парсера или 0A000 feature_not_supported.
NULL handling
- Все типы допускают
NULL, если колонка не объявлена какNOT NULL. - В
ORDER BY ASCзначенияNULLтрактуются как наибольшие (выводятся последними). - Явное управление
NULLS FIRST/NULLS LASTне поддерживается —0A000.
Type casting
AngaraBase поддерживает PostgreSQL-синтаксис приведения типов:
SELECT '42'::INTEGER;
SELECT id::TEXT FROM t;
Приведение между несовместимыми типами приводит к runtime-ошибке с соответствующим SQLSTATE.
Expected SQLSTATE
| Ситуация | SQLSTATE |
|---|---|
| Неподдерживаемый тип в DDL | 0A000 |
INTERVAL арифметика | 0A000 |
NULLS FIRST / NULLS LAST | 0A000 |
| Невалидный cast | Runtime error |
Links
- SQL compatibility overview: overview.md
- DDL (CREATE TABLE с типами): ddl.md
- Known issues: Known issues
DDL — Data Definition Language
Goal
Справочник поддерживаемых DDL-операций: создание, изменение и удаление таблиц, индексов и ограничений.
CREATE TABLE
Basic form
CREATE TABLE t (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL,
v BIGINT
);
With table options
CREATE TABLE events (
id INTEGER PRIMARY KEY,
ts TIMESTAMP NOT NULL,
data TEXT
) WITH (append_only = true);
CREATE TABLE ledger (
id INTEGER PRIMARY KEY,
amount BIGINT,
ref_id INTEGER
) WITH (mutation_policy = 'no_delete');
Constraints
PRIMARY KEY— обязателен для каждой таблицы (ровно один).NOT NULL— колонка не принимаетNULL.FOREIGN KEY ... NOT ENFORCED— декларативный FK без runtime-проверки.
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
parent_id INTEGER NOT NULL,
FOREIGN KEY (parent_id) REFERENCES parents (id) NOT ENFORCED
);
Enforced foreign keys не поддерживаются — попытка создать FK без NOT ENFORCED вернёт 0A000.
ALTER TABLE
Table-level options
ALTER TABLE t SET (append_only = true);
ALTER TABLE t SET (append_only = false);
ALTER TABLE t SET (mutation_policy = 'no_delete');
ALTER TABLE t SET (mutation_policy = 'unrestricted');
ALTER TABLE t SET (stats_level_max = 2);
ALTER TABLE t SET (stats_reservoir_size = 1000);
Column-level options
ALTER TABLE t ALTER COLUMN v SET (stats_level_max = 1);
Table options reference
| Option | Values | Default | Description |
|---|---|---|---|
append_only | true / false | false | Reject UPDATE/DELETE (SQLSTATE 42809) |
mutation_policy | unrestricted / append_only / no_delete | unrestricted | Fine-grained mutation control |
stats_level_max | 0–3 | 0 | Max statistics collection level |
stats_reservoir_size | ≥ 1 | Engine default | Reservoir sample size for Level 2 stats |
append_only = true эквивалентен mutation_policy = 'append_only'.
DROP TABLE
DROP TABLE t;
При DROP TABLE каскадно удаляются связанные owned-последовательности
(SERIAL/IDENTITY), даже без CASCADE (поведение PostgreSQL).
CREATE / ALTER / DROP SEQUENCE
AngaraBase поддерживает first-class объекты-последовательности
(SEQUENCE) — RM-0.6.3.7, RFC-2026-497. Они сохраняются в sys_catalog,
переживают рестарт сервера и обслуживают SERIAL/BIGSERIAL и
GENERATED [ALWAYS|BY DEFAULT] AS IDENTITY.
CREATE SEQUENCE
CREATE SEQUENCE s1; -- start=1, inc=1, без верхней границы
CREATE SEQUENCE s2 START WITH 100 INCREMENT BY 5;
CREATE SEQUENCE s3 MINVALUE 1 MAXVALUE 999 CYCLE; -- циклический счётчик
CREATE SEQUENCE IF NOT EXISTS s1; -- идемпотентно
Опции (порядок свободный):
START WITH n, INCREMENT BY n, MINVALUE n / NO MINVALUE,
MAXVALUE n / NO MAXVALUE, CYCLE / NO CYCLE.
ALTER SEQUENCE
ALTER SEQUENCE s1 INCREMENT BY 10;
ALTER SEQUENCE s1 RESTART WITH 1; -- сбросить счётчик
ALTER SEQUENCE s1 MAXVALUE 1000 NO CYCLE;
ALTER SEQUENCE t_id_seq OWNED BY t.id; -- привязка к колонке
ALTER SEQUENCE s1 OWNED BY NONE; -- отвязать
DROP SEQUENCE
DROP SEQUENCE s1;
DROP SEQUENCE IF EXISTS s1;
DROP SEQUENCE s1 CASCADE;
Поведение функций
См. dml.md — раздел «Sequence functions» (nextval, currval,
setval).
SQLSTATE
| Ситуация | SQLSTATE |
|---|---|
CREATE SEQUENCE с уже существующим именем без IF NOT EXISTS | 42P07 |
DROP SEQUENCE несуществующего имени без IF EXISTS | 42P01 |
ALTER SEQUENCE несуществующей последовательности | 42P01 |
MINVALUE > MAXVALUE или START вне [MIN..MAX] | 22023 |
CREATE INDEX
AngaraBase поддерживает одноколоночные индексы двух типов: btree (default) и brin.
-- btree (default)
CREATE INDEX idx_t_v ON t (v);
-- btree (explicit)
CREATE INDEX idx_t_v ON t USING btree (v);
-- brin
CREATE INDEX idx_events_ts ON events USING brin (ts);
BRIN supported key types
| Type | Aliases |
|---|---|
int | int4, integer |
bigint | int8 |
date | — |
timestamp | — |
timestamptz | — |
BRIN остаётся accelerator path с heap fetch + MVCC predicate recheck.
Current bounds
- Только одноколоночные индексы.
- Составные и выражения-индексы не поддерживаются —
0A000. - Unsupported index methods (GIN, GiST и др.) —
0A000.
Expected SQLSTATE
| Ситуация | SQLSTATE |
|---|---|
| Неподдерживаемая DDL-форма | 0A000 |
| Enforced FK | 0A000 |
| Составной / expression индекс | 0A000 |
| Неподдерживаемый index method | 0A000 |
stats_level_max вне [0..3] | 22023 |
Links
- Data types: data-types.md
- DML (INSERT/UPDATE/DELETE): dml.md
- Partitioning (CREATE TABLE … PARTITION BY): partitioning.md
- Known issues: Known issues
DML — Data Manipulation Language
Goal
Справочник поддерживаемых DML-операций и поведение mutation policy.
INSERT
INSERT INTO t (id, v) VALUES (1, 100);
INSERT INTO t (id, v) VALUES (2, 200), (3, 300);
Для секционированных таблиц INSERT в родительскую таблицу автоматически маршрутизирует строку в подходящую
партицию. Если подходящая партиция (и DEFAULT) отсутствует — 23514 check_violation.
INSERT … SELECT
RM-0.6.3.7 (RFC-2026-497, S8): источник INSERT — произвольный
SELECT-запрос. Колонки результата сопоставляются с целевыми по позиции
(или по явному списку колонок); SERIAL/IDENTITY/DEFAULT резолвятся
для каждой строки независимо.
INSERT INTO archive (id, v) SELECT id, v FROM t WHERE created_at < '2025-01-01';
INSERT INTO log (note) SELECT 'rebuilt:' || name FROM rebuilt_items;
INSERT … ON CONFLICT (UPSERT)
RM-0.6.3.7 (RFC-2026-497, S9): поддерживается одно-колоночный конфликтный
target (или PK по умолчанию). EXCLUDED.<col> ссылается на предложенную
строку.
-- DO NOTHING (раннее поведение, теперь принимает явный target):
INSERT INTO t (id, v) VALUES (1, 100) ON CONFLICT (id) DO NOTHING;
-- DO UPDATE SET ... [WHERE ...]
INSERT INTO counters (key, n)
VALUES ('hits', 1)
ON CONFLICT (key) DO UPDATE SET n = counters.n + EXCLUDED.n;
-- WHERE-фильтр над существующей строкой (PG-семантика: конфликт + WHERE-false = silent no-op):
INSERT INTO inventory (sku, qty)
VALUES ('A', 5)
ON CONFLICT (sku) DO UPDATE SET qty = EXCLUDED.qty
WHERE inventory.qty < EXCLUDED.qty;
Не поддерживается:
- мультиколоночный target (
ON CONFLICT (a, b)) →0A000; ON CONFLICT ON CONSTRAINT <name>→0A000.
UPDATE
UPDATE t SET v = 999 WHERE id = 1;
Начиная с RM-0.6.5.5, UPDATE SET поддерживает функциональные выражения и приведение типов:
UPDATE t SET write_date = NOW() WHERE id = 1;UPDATE t SET ts = '2026-05-07 14:30:00'::timestamp WHERE id = 1;UPDATE t SET day = date_trunc('day', NOW()) WHERE id = 1;
Поддерживаются NOW(), CURRENT_TIMESTAMP, CURRENT_DATE, date_trunc() и явные CAST (синтаксис ::).
DELETE
DELETE FROM t WHERE id = 2;
RETURNING
RM-0.6.3.7 (RFC-2026-497, S10): RETURNING поддержан для multi-row
INSERT, UPDATE, DELETE. В проекции допустимы *, явный список
колонок и выражения. Для INSERT ... ON CONFLICT DO UPDATE возвращается
пост-апдейт строка (как в PostgreSQL).
INSERT INTO t (v) VALUES (100), (200), (300) RETURNING id, v;
UPDATE t SET v = v + 1 WHERE v > 0 RETURNING id, v AS new_v;
DELETE FROM t WHERE v IS NULL RETURNING id;
Sequence functions
RM-0.6.3.7 (RFC-2026-497): nextval / currval / setval для
объектов SEQUENCE (см. ddl.md — раздел «CREATE / ALTER /
DROP SEQUENCE»). Не транзакционные: gap-on-rollback корректное поведение.
SELECT nextval('s1'); -- 1, 2, 3, ...; overflow без CYCLE → 2200H
SELECT currval('s1'); -- последнее значение, выданное в ЭТОЙ сессии
SELECT setval('s1', 100); -- last_value=100, is_called=true; следующий nextval = 101
SELECT setval('s1', 50, false); -- следующий nextval = 50
currval — session-bound: возвращает значение последнего nextval
(или setval(_, _, true)) в той же pgwire-сессии. Если в текущей
сессии nextval ещё не вызывался — 55000 object_not_in_prerequisite_state,
независимо от того, что nextval был вызван в других сессиях.
SERIAL / IDENTITY
SERIAL / BIGSERIAL и GENERATED [ALWAYS|BY DEFAULT] AS IDENTITY
автоматически создают owned-последовательность <table>_<col>_seq,
которая удаляется вместе с таблицей.
CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT);
INSERT INTO users (name) VALUES ('alice'), ('bob') RETURNING id;
-- id заполняется через nextval('users_id_seq')
CREATE TABLE orders (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
amount NUMERIC
);
INSERT INTO orders (id, amount) VALUES (42, 100);
-- → 428C9 generated_always: id колонка GENERATED ALWAYS
CREATE TABLE invoices (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
total NUMERIC
);
INSERT INTO invoices (id, total) VALUES (DEFAULT, 250) RETURNING id;
INSERT INTO invoices (id, total) VALUES (1000, 250); -- explicit OK
SELECT
SELECT id, v FROM t WHERE v > 50 ORDER BY id;
Подробно о запросах (CTE, JOIN, GROUP BY и т.д.) — см. queries.md.
TRUNCATE
TRUNCATE TABLE t;
TRUNCATE — DDL-сброс таблицы. Для append-only таблиц это единственный способ удалить данные.
Mutation policy enforcement
Mutation policy контролирует допустимые DML-операции на таблице.
append_only
| Операция | Результат |
|---|---|
INSERT | Разрешён |
UPDATE | Отклонён — 42809 wrong_object_type |
DELETE | Отклонён — 42809 wrong_object_type |
TRUNCATE | Разрешён (DDL reset) |
no_delete
| Операция | Результат |
|---|---|
INSERT | Разрешён |
UPDATE (non-PK, non-FK columns) | Разрешён |
UPDATE PK column (id) | Отклонён — 42809 wrong_object_type |
UPDATE FK child column | Отклонён — 42809 wrong_object_type |
DELETE | Отклонён — 42809 wrong_object_type |
TRUNCATE | Отклонён — 42809 wrong_object_type |
unrestricted
Все DML-операции разрешены (поведение по умолчанию).
Autocommit vs explicit transactions
По умолчанию каждый DML-запрос выполняется в autocommit-режиме (неявная транзакция, фиксируется сразу).
Для явных транзакций:
BEGIN;
INSERT INTO t (id, v) VALUES (10, 1000);
UPDATE t SET v = 2000 WHERE id = 10;
COMMIT;
ROLLBACK откатывает все изменения текущей транзакции.
Expected SQLSTATE
| Ситуация | SQLSTATE |
|---|---|
UPDATE/DELETE on append-only table | 42809 |
DELETE/TRUNCATE under no_delete | 42809 |
PK/FK UPDATE under no_delete | 42809 |
| Insert into partitioned table, no matching partition | 23514 |
nextval overflow (без CYCLE) | 2200H |
currval до первого nextval в этой сессии | 55000 |
setval value вне [MINVALUE..MAXVALUE] | 22023 |
Несуществующая sequence (nextval/currval/setval/DROP SEQUENCE без IF EXISTS) | 42P01 |
INSERT в GENERATED ALWAYS AS IDENTITY колонку с явным non-NULL | 428C9 |
INSERT ... ON CONFLICT (a, b) (multi-column target) | 0A000 |
INSERT ... ON CONFLICT ON CONSTRAINT <name> | 0A000 |
Links
- DDL (CREATE TABLE, mutation policy options): ddl.md
- Queries (SELECT details): queries.md
- Partitioning: partitioning.md
- Known issues: Known issues
Queries
Goal
Справочник поддерживаемых форм запросов: CTE, JOIN, агрегация, сортировка, статистические поверхности.
Non-recursive WITH (CTE)
AngaraBase поддерживает ограниченные (non-recursive) CTE как derived source в FROM:
WITH recent AS (
SELECT id, v FROM t WHERE v > 100
)
SELECT r.id, r.v
FROM recent r
ORDER BY r.id;
Supported CTE projection forms
WITH c AS (SELECT id, v FROM t)
SELECT * FROM c WHERE id < 10;
Explicitly unsupported
WITH RECURSIVE—0A000 feature_not_supported- Data-modifying CTEs (
WITH ... INSERT/UPDATE/DELETE) —0A000 feature_not_supported
JOINs
SELECT a.id, b.name
FROM orders a
INNER JOIN customers b ON a.customer_id = b.id;
SELECT a.id, b.name
FROM orders a
LEFT JOIN customers b ON a.customer_id = b.id;
Поддерживаются: INNER JOIN, LEFT JOIN.
ORDER BY
SELECT * FROM t ORDER BY v;
SELECT * FROM t ORDER BY v ASC;
SELECT * FROM t ORDER BY v DESC;
ORDER BY <expr> поддерживает ограниченные скалярные выражения, уже поддерживаемые движком.
Поддержка псевдонимов (Aliases)
ORDER BY может ссылаться на псевдонимы (алиасы), определённые в SELECT-списке с помощью ключевого слова AS. Это работает как для обычных колонок, так и для результатов агрегации:
-- Алиас для выражения
SELECT x * 2 AS doubled FROM t ORDER BY doubled;
-- Алиас для агрегации
SELECT grp, sum(amount) AS total
FROM t
GROUP BY grp
ORDER BY total DESC;
Порядковые номера колонок (Ordinals)
Поддерживается сортировка по порядковому номеру колонки в SELECT-списке (1-based), согласно стандарту SQL:2011:
-- Сортировка по первой колонке (a)
SELECT a, b FROM t ORDER BY 1;
-- Сортировка по второй колонке (b) в обратном порядке
SELECT a, b FROM t ORDER BY 2 DESC;
Если указанный номер выходит за пределы количества колонок в запросе (или равен 0), возвращается ошибка 42P10 (invalid_column_reference).
NULL ordering
- В
ASCпорядкеNULLтрактуется как наибольшее значение (выводится последним). - В
DESCпорядкеNULLвыводится первым. - Явное
NULLS FIRST/NULLS LASTне поддерживается —0A000.
GROUP BY / HAVING
SELECT v, COUNT(*) AS cnt
FROM t
GROUP BY v
HAVING COUNT(*) > 1;
LIMIT / OFFSET
SELECT * FROM t ORDER BY id LIMIT 10;
SELECT * FROM t ORDER BY id LIMIT 10 OFFSET 20;
Ошибки в выражениях (Expression Errors)
При использовании несовместимых типов в арифметических выражениях (например, попытка сложения строки с числом 'строка' + 1), AngaraBase возвращает ошибку 42883 (undefined_function / operator not found).
Примечание: строковые литералы, содержащие числа (например, '123'), могут автоматически приводиться к числовому типу в зависимости от контекста.
Unsupported query forms
| Form | SQLSTATE |
|---|---|
UNION / INTERSECT / EXCEPT | 0A000 |
Window functions (OVER (...)) | 0A000 |
ORDER BY ... NULLS FIRST|LAST | 0A000 |
WITH RECURSIVE | 0A000 |
| Data-modifying CTEs | 0A000 |
AngaraStat surfaces
AngaraBase предоставляет встроенные статистические представления.
sys.table_stats
| Column | Description |
|---|---|
stats_level_max | Max collection level configured |
last_committed_rowid | Last committed row ID |
last_insert_epoch | Epoch of last insert |
last_mutation_epoch | Epoch of last mutation |
sys.column_stats
| Column | Description |
|---|---|
ndv_approx | Approximate number of distinct values (HLL) |
col_min | Column minimum (typed Value) |
col_max | Column maximum (typed Value) |
null_count | Number of NULLs |
stats_epoch | Stats collection epoch |
hll_enabled | Whether HLL tracking is active |
histogram_bounds | Equi-depth histogram boundaries (Level 2) |
mcv_values | Most common values (Level 2) |
mcv_frequencies | MCV frequencies (Level 2) |
reservoir_size | Reservoir sample size (Level 2) |
reservoir_epoch | Reservoir epoch (Level 2) |
reservoir_drift_count | Drift count since last reservoir refresh (Level 2) |
SELECT * FROM sys.table_stats WHERE table_name = 'events';
SELECT * FROM sys.column_stats WHERE table_name = 'events' AND column_name = 'ts';
Expected SQLSTATE
| Ситуация | SQLSTATE |
|---|---|
WITH RECURSIVE | 0A000 |
| Data-modifying CTE | 0A000 |
UNION / INTERSECT / EXCEPT | 0A000 |
| Window functions | 0A000 |
ORDER BY ... NULLS FIRST|LAST | 0A000 |
ORDER BY ordinal out of range | 42P10 |
| Expression type error | 42883 |
Links
- DML operations: dml.md
- DDL (stats options): ddl.md
- SQL compatibility overview: overview.md
- Known issues: Known issues
Table partitioning
Goal
Справочник секционирования таблиц: RANGE, LIST, управление партициями и runtime-поведение.
PARTITION BY RANGE
CREATE TABLE events (
id INTEGER PRIMARY KEY,
ts DATE NOT NULL,
data TEXT
) PARTITION BY RANGE (ts);
Range partitions
CREATE TABLE events_2025 PARTITION OF events
FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');
CREATE TABLE events_2026 PARTITION OF events
FOR VALUES FROM ('2026-01-01') TO ('2027-01-01');
PARTITION BY LIST
CREATE TABLE metrics (
id INTEGER PRIMARY KEY,
region VARCHAR(20) NOT NULL,
value BIGINT
) PARTITION BY LIST (region);
List partitions
CREATE TABLE metrics_eu PARTITION OF metrics
FOR VALUES IN ('eu-west', 'eu-east');
CREATE TABLE metrics_us PARTITION OF metrics
FOR VALUES IN ('us-east', 'us-west');
DEFAULT partition
CREATE TABLE events_other PARTITION OF events DEFAULT;
Строки, не подпадающие ни под одну партицию, попадают в DEFAULT.
Если DEFAULT не существует и подходящая партиция не найдена — 23514 check_violation.
ALTER TABLE — attach / detach
ALTER TABLE events ATTACH PARTITION events_2027
FOR VALUES FROM ('2027-01-01') TO ('2028-01-01');
ALTER TABLE events DETACH PARTITION events_2025;
DROP PARTITION
DROP PARTITION events_2025;
Runtime behavior
INSERT routing
INSERT в родительскую таблицу автоматически маршрутизирует строку в подходящую дочернюю партицию:
INSERT INTO events (id, ts, data) VALUES (1, '2026-06-15', 'test');
-- → events_2026
Если ни одна партиция не подходит и DEFAULT отсутствует:
ERROR: 23514: new row for relation "events" violates check constraint
Append-only inheritance
Если родительская таблица объявлена как append_only = true:
- Все присоединённые партиции наследуют режим append-only.
- Партиция не может отключить
append_onlyпока родитель остаётся append-only —42809.
CREATE TABLE events (
id INTEGER PRIMARY KEY,
ts DATE NOT NULL
) PARTITION BY RANGE (ts) WITH (append_only = true);
-- partitions inherit append_only
CREATE TABLE events_2026 PARTITION OF events
FOR VALUES FROM ('2026-01-01') TO ('2027-01-01');
Current v0 bounds
| Ограничение | Статус |
|---|---|
| Одноколоночный partition key | Единственный поддерживаемый |
| Hash partitioning | Не поддерживается |
| Subpartitioning | Не поддерживается |
Неподдерживаемые формы возвращают 0A000 feature_not_supported.
Expected SQLSTATE
| Ситуация | SQLSTATE |
|---|---|
| No matching partition, no DEFAULT | 23514 |
| Hash partitioning | 0A000 |
| Multi-column partition key | 0A000 |
| Subpartitioning | 0A000 |
| Disable append-only on child (parent is append-only) | 42809 |
Links
- DDL reference: ddl.md
- DML (INSERT routing): dml.md
- SQL compatibility overview: overview.md
- Known issues: Known issues
Security model (overview)
Goal
Understand the layered security architecture of AngaraBase: which controls exist, how they interact, and how to verify your instance is running in a secure configuration.
Prerequisites
- A running AngaraBase instance (local or staging).
- SQL session access (pgwire).
- Basic understanding of roles and tables in your database.
Security model (layers)
AngaraBase uses a layered defence model. Each layer is independent and composable — no single layer bypass compromises the whole.
Layer 1 — Transport and identity
- TLS protects the wire protocol.
- Auth modes (
trust,scram,cert) control how clients prove identity. - Fail-closed: remote bind without TLS is rejected when
tls.require_on_remote_bind = true.
See authentication.md for setup and verification.
Layer 2 — Authorization and data visibility
- RBAC (roles, grants, privileges) decides whether an operation is allowed at all.
- RLS (row-level security policies) decides which rows are visible or modifiable.
- Deny-by-default: enabling RLS without policies blocks all rows, including for the table owner.
See authorization.md for SQL surface and introspection.
Layer 3 — Controlled privilege escalation
- Break-glass is the only way to bypass RLS — even
SUPERUSERcannot. - Activation requires a mandatory
REASONandTTL. - Every query during break-glass generates a dedicated audit entry.
See break-glass.md for the full lifecycle.
Layer 4 — Audit and accountability
- Audit chain is append-only and tamper-evident (SHA-256 chain hash).
- Scope: auth, DDL, DCL, policy changes, break-glass lifecycle.
- DML audit policy: configurable
off|allowlist|denylistper table.
See audit.md for configuration and verification.
Layer 5 — Data-at-rest protection
- TDE (Transparent Data Encryption) covers pages, WAL, and audit sink.
- Fail-closed: missing or invalid key material prevents startup and audit I/O.
See encryption.md for TDE setup and key management.
Layer 6 — Client-encrypted columns (v0)
- Server stores ciphertext + metadata (
alg,mode,key_id) but never the keys. DETERMINISTICmode allows equality predicates;RANDOMIZEDrejects server-side predicates (0A000).
See encryption.md for the SQL surface and operator rules.
How features work together
| Combination | Behaviour |
|---|---|
| RBAC + RLS | RBAC decides “is this operation allowed at all”; RLS further restricts “which rows”. |
| Break-glass + audit | Temporary elevation is accepted only with a reason and full traceability in the audit chain. |
| TDE + audit | When TDE is enabled, audit bytes on disk are encrypted; sys.audit_log remains readable only with the correct key. |
| Client encryption + SQL bounds | Deterministic mode allows a limited predicate path; randomized mode fail-closes unsupported server-side operations. |
Quick security verification
Step 1 — Check effective settings
SELECT name, value
FROM sys.settings
WHERE name LIKE 'tls.%'
OR name LIKE 'security.%'
OR name LIKE 'audit.%'
ORDER BY name;
Returns effective security knobs without exposing secrets.
Step 2 — Check security surfaces
SELECT * FROM angara_user_roles() LIMIT 20;
SELECT * FROM angara_table_policies('public.users');
SELECT * FROM angara_break_glass_status();
SELECT * FROM angara_audit_verify_chain();
Validates that key introspection/verification functions are available and responsive.
Step 3 — Validate RLS explanation surface
SELECT * FROM angara_effective_rls_predicate('public.users');
Returns the effective predicate and helps explain row-visibility behaviour.
Expected result
sys.settingsshows security knobs without secrets.- Security functions return data (or empty results) without internal errors.
- Unsupported operations terminate with an explicit SQLSTATE (
0A000,42501, or22023) — never a silent bypass.
Troubleshooting
42501 insufficient_privilegeon security DDL/ops Check user roles and session context; see authorization.md.0A000 feature_not_supportedin policy/encrypted path This is a bounded contract (not a bug) — use the supported syntax or mode.- TDE enabled but audit/data I/O fails Verify master key presence and correctness; fail-closed is expected. See encryption.md.
- Need a bug-report artifact? Follow the bundle steps in ../reference/support.md.
Links
-
Security knobs registry:
angarabook/src/operations/security-operations.md -
Authentication: authentication.md
-
Authorization: authorization.md
-
Audit: audit.md
-
Encryption: encryption.md
-
Break-glass: break-glass.md
-
Hardening runbook: hardening.md
Authentication
Goal
Configure and verify transport security (TLS) and client authentication modes so that only identified clients can connect to AngaraBase.
Prerequisites
- Access to the server configuration (TOML config and/or environment variables).
- TLS certificate and key files (for
scramorcertmodes with remote clients). - Ability to restart the server after configuration changes.
Auth modes
AngaraBase supports three authentication modes, set via ANGARABASE_AUTH_MODE or security.auth_mode in the
config:
| Mode | When to use | Identity proof |
|---|---|---|
trust | Local development / testing only | None — any connecting client is accepted |
scram | Production and staging | SCRAM-SHA-256 password challenge |
cert | mTLS environments | Client TLS certificate validated against CA |
Default: trust (requires explicit opt-in flag for remote bind — see Startup safety below).
Steps
1) Configure TLS
TLS is controlled in the [tls] section of angarabase.conf:
[tls]
enabled = true
cert_path = "/etc/angarabase/tls/server.crt"
key_path = "/etc/angarabase/tls/server.key"
require_on_remote_bind = true
Or via environment variables:
export ANGARABASE_TLS_ENABLED=1
export ANGARABASE_TLS_CERT_PATH=/etc/angarabase/tls/server.crt
export ANGARABASE_TLS_KEY_PATH=/etc/angarabase/tls/server.key
export ANGARABASE_TLS_REQUIRE_ON_REMOTE_BIND=1
require_on_remote_bind = true enforces fail-closed behaviour: if the server binds to a non-loopback address
and TLS is not enabled, startup is refused.
2) Set auth mode
export ANGARABASE_AUTH_MODE=scram
Or in angarabase.conf:
[security]
auth_mode = "scram"
3) SCRAM setup
When auth_mode = scram, the superuser must be bootstrapped with a password at init time:
angarabase-server --init /var/lib/angarabase \
--superuser admin \
--superuser-password 'strong-password' \
--auth-mode scram
The password is converted to a SCRAM-SHA-256 verifier before it touches disk — plaintext is never stored.
Additional users are created via SQL:
CREATE USER app_reader WITH PASSWORD 'change-me';
Password storage format: SCRAM-SHA-256$<iterations>:<salt>$<StoredKey>:<ServerKey>.
4) Startup safety
To protect against accidental production use of trust mode:
trustmode on a non-loopback bind address requires the explicit flag--allow-insecure-no-auth.- Without this flag the server refuses to start (fail-closed).
scramorcertmodes do not require the flag.
5) Verify effective config from SQL
After startup, confirm the active settings:
SELECT name, value
FROM sys.settings
WHERE name IN (
'tls.enabled',
'tls.require_on_remote_bind',
'security.auth_mode'
)
ORDER BY name;
No secret material (keys, passwords, verifiers) appears in sys.settings.
Expected result
- In
scrammode, unauthenticated connections are rejected. - In
certmode, clients without a valid certificate are rejected. truston remote bind without--allow-insecure-no-authprevents startup.sys.settingsconfirms the effective auth mode and TLS state without leaking secrets.
Troubleshooting
- Server refuses to start in trust mode
You are binding to a non-loopback address. Either switch to
scram/certor pass--allow-insecure-no-authfor development. authentication failed for user "..."on connect Verify the password or certificate; check thatsecurity.auth_modematches the client’s auth method.- TLS handshake failure
Confirm
cert_pathandkey_pathpoint to valid, non-expired files; verify the client’ssslmodesetting. - Init refused: scram requires password
Provide
--superuser-password(or--superuser-password-file) when--auth-mode scramis set. - Need a bug-report artifact? See ../reference/support.md.
Links
- Security model overview: overview.md
- Hardening runbook: hardening.md
- Configuration reference: ../operations/configuration.md
- Security knobs registry:
angarabook/src/operations/security-operations.md
Authorization (RBAC and RLS)
Goal
Set up role-based access control and row-level security policies so that users see and modify only the data they are permitted to.
Prerequisites
- SQL session with a user that has
SUPERUSERorSECURITY_ADMINprivileges. - A test table (e.g.
public.users) with representative data.
RBAC — users, roles, privileges
Create a user and grant a role
CREATE USER app_reader WITH PASSWORD 'change-me';
GRANT reader TO app_reader;
GRANT SELECT ON public.users TO reader;
Object-level grants
GRANT SELECT ON TABLE public.orders TO analyst;
GRANT INSERT, UPDATE ON TABLE public.orders TO writer_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analyst;
Default policy is deny-by-default: a user without an explicit GRANT cannot access another user’s tables.
Built-in role hierarchy
SUPERUSER
├── SECURITY_ADMIN — policy, audit, key, and break-glass management
├── DBA — ops (shutdown, backup, restore, settings, diagnostics)
├── CREATEROLE — CREATE/ALTER/DROP USER and ROLE
└── CREATEDB — CREATE DATABASE
SUPERUSER does not bypass RLS — only BREAK_GLASS can (see break-glass.md).
RLS — row-level security
Enable RLS on a table
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;
After this, the table follows deny-by-default: no rows are visible to anyone (including the owner) until at least one policy is created.
Create a security policy
CREATE SECURITY POLICY p_users_tenant ON public.users
USING (tenant_id = current_setting('app.tenant_id')::int);
The USING predicate is injected as an automatic WHERE clause on SELECT, INSERT, UPDATE, and
DELETE.
RLS enforcement rules
| Operation | Behaviour |
|---|---|
SELECT | Rows that fail the predicate are silently excluded. |
INSERT | The new row must satisfy the predicate; otherwise an error is raised. |
UPDATE | The old row must be visible (silent skip if not); the new row must satisfy the predicate (error if not). |
DELETE | The row must be visible (silent skip if not; returns 0 affected rows). |
Multiple policies on one table use AND semantics — all must pass.
RLS v1 masking metadata
Policies can include a MASK clause for user-facing field masking:
ALTER SECURITY POLICY p_users_tenant ON public.users
USING (tenant_id = current_setting('app.tenant_id')::int)
MASK (email USING 'partial');
Supported mask types in v1:
| Mask | Effect |
|---|---|
partial | Returns a stable masked shape of the original value. |
nullify | Returns NULL in place of the real value. |
Unsupported mask expressions return 0A000 feature_not_supported.
Unsupported predicates — fail-closed
In the IR/planner mode, complex predicates that cannot be safely rewritten (subqueries, arbitrary function calls, JOINs) are rejected:
ERROR: 0A000 feature_not_supported
unsupported RLS predicate form
This is a bounded contract, not a bug. Use the supported predicate language (column references,
current_setting(), current_user, literals, comparisons, AND/OR/NOT, IN, IS [NOT] NULL, type
casts).
Introspection
SELECT * FROM angara_table_policies('public.users');
SELECT * FROM angara_effective_rls_predicate('public.users');
SELECT * FROM sys.users;
SELECT * FROM sys.roles;
SELECT * FROM sys.user_roles;
SELECT * FROM sys.role_privileges;
SELECT * FROM sys.object_grants;
SELECT * FROM sys.my_privileges;
SELECT * FROM sys.security_policies;
SELECT * FROM angara_user_roles('alice');
SELECT * FROM angara_user_privileges('alice');
SELECT angara_has_privilege('alice', 'SELECT', 'TABLE', 'public.orders');
SELECT angara_is_rls_active('public.users');
angara_effective_rls_predicate() shows the combined predicate, provenance, and mask metadata for a table —
useful for explaining row-visibility behaviour.
Expected result
- RBAC grants control object-level access; users without grants are denied.
- RLS predicates filter rows transparently on
SELECT/INSERT/UPDATE/DELETE. angara_table_policiesreflects active policies, mask metadata, and provenance.- Unsupported paths return a deterministic SQLSTATE, never a silent bypass.
Troubleshooting
42501 insufficient_privilegeThe current user lacks the required role or grant. Checksys.my_privilegesandangara_user_roles().0A000 feature_not_supportedon RLS policy or mask The predicate or mask expression is outside the supported v1 syntax. Simplify the expression.- Rows unexpectedly invisible after enabling RLS
Deny-by-default is working correctly. Create a
SECURITY POLICYwith aUSINGpredicate to allow the intended rows. - Need a bug-report artifact? See ../reference/support.md.
Links
- Security model overview: overview.md
- Break-glass (RLS bypass): break-glass.md
- Audit: audit.md
- SQL compatibility: ../sql-reference/overview.md
- Known issues: ../reference/known-issues.md
Audit
Goal
Understand and configure AngaraBase’s tamper-evident audit subsystem: chain verification, DML audit policy, and JSON export.
Prerequisites
- A running AngaraBase instance with audit enabled (default).
- SQL session with
SECURITY_ADMINorSUPERUSERprivileges (for configuration changes). - Write-accessible path for the audit log file.
Audit chain concept
AngaraBase maintains an append-only, tamper-evident audit trail:
- Every security-relevant event (auth, DDL, DCL, policy changes, break-glass lifecycle) produces an
AuditEvent. - Each event contains
prev_hash— a SHA-256 hash of the preceding entry, forming a hash chain. - Breaking or modifying any entry invalidates all subsequent hashes, making tampering detectable.
- The chain is separate from the transactional data path — audit events are recorded even for rolled-back transactions.
Audit scope
| Event category | v0 (baseline) | v1 |
|---|---|---|
| Auth (success / failure / disconnect) | Yes | Yes |
| DDL (CREATE / ALTER / DROP) | Yes | Yes |
| DCL (GRANT / REVOKE) | Yes | Yes |
| User / role management | Yes | Yes |
| Security policy changes | Yes | Yes |
| Break-glass lifecycle | Yes | Yes |
| DML (SELECT / INSERT / UPDATE / DELETE) | No | Yes (policy-driven) |
| Key operations | No | Yes |
Steps
1) Verify chain integrity
SELECT * FROM angara_audit_verify_chain();
Returns is_valid, first_broken_seq, and details. A healthy chain returns is_valid = true.
2) Query the audit log
SELECT * FROM sys.audit_log
WHERE event_type = 'break_glass_query'
AND timestamp > now() - INTERVAL '24 hours'
ORDER BY seq DESC
LIMIT 50;
Columns: seq, timestamp, event_type, user_name, auth_method, client_ip, database,
session_claims, payload, prev_hash.
3) Configure audit v1 DML policy
DML audit is controlled by three knobs:
export ANGARABASE_AUDIT_DML_MODE=allowlist
export ANGARABASE_AUDIT_DML_ALLOWLIST=public.users,public.payments
| Mode | Behaviour |
|---|---|
off | No DML events recorded (default). |
allowlist | Record DML only for listed schema.table entries — targeted compliance. |
denylist | Record DML for all tables except those listed — broad coverage with exclusions. |
Use ANGARABASE_AUDIT_DML_DENYLIST for the denylist.
Malformed policy or ambiguous object references cause a startup/config-apply rejection (fail-closed).
4) Configure audit log path
export ANGARABASE_AUDIT_LOG_PATH=/var/lib/angarabase/audit/audit.jsonl
The path must be writable. If the path is inaccessible, audit writes fail-closed.
5) Configure JSON export
export ANGARABASE_AUDIT_EXPORT_JSON_ENABLED=1
export ANGARABASE_AUDIT_EXPORT_RATE_LIMIT_RPS=50
Export is bounded and rate-limited. Export failures are reported but never expose secret payload fragments in error text.
6) TDE interaction
When TDE is enabled (ANGARABASE_TDE_ENABLE=1), the audit sink on disk is encrypted transparently:
- Key:
audit_dek = KDF(master_key, domain="audit-v0", key_id). sys.audit_logdecrypts on read when the correct key is available.- Without the key, audit read/write is impossible (fail-closed).
- Encrypted audit data remains encrypted in backups and copied artefacts.
See encryption.md for TDE configuration.
Expected result
angara_audit_verify_chain()returnsis_valid = truefor an intact chain.sys.audit_logshows auth, DDL, DCL, policy, and break-glass events.- With DML policy set to
allowlistordenylist, matching DML operations appear in the audit log. - TDE-encrypted audit files are unreadable without the master key.
Troubleshooting
angara_audit_verify_chain()returnsis_valid = falseThe chain has been tampered with or corrupted. Note thefirst_broken_seqand investigate the audit file. The audit subsystem can self-repair by truncating to the last valid entry.- DML events not appearing in audit log
Check
audit.dml_mode— default isoff. Verify that the target table is in the allowlist (or not in the denylist). - Audit write failures after enabling TDE
Verify
ANGARABASE_TDE_MASTER_KEY_HEXand key validity. Fail-closed behaviour is expected when key material is missing. - Break-glass activation fails with “audit subsystem unavailable” Break-glass requires a healthy audit subsystem. Fix the audit path or key material first.
- Need a bug-report artifact? See ../reference/support.md.
Links
- Security model overview: overview.md
- Encryption (TDE): encryption.md
- Break-glass: break-glass.md
- Configuration reference: ../operations/configuration.md
Encryption
Goal
Configure data-at-rest protection with TDE and understand the server-side contract for client-encrypted columns.
Prerequisites
- Access to server environment variables or configuration file.
- A 256-bit master key (64 hex characters) for TDE.
- Ability to restart the server after TDE changes.
TDE — Transparent Data Encryption (v0)
TDE encrypts data at rest without application changes. When enabled, the following are encrypted:
- Storage pages (the
.adbdata file). - WAL (write-ahead log) entries.
- Audit sink on disk (JSONL trail).
Configure TDE
export ANGARABASE_TDE_ENABLE=1
export ANGARABASE_TDE_MASTER_KEY_HEX=<64-hex-characters>
export ANGARABASE_TDE_MASTER_KEY_ID=master-prod-2026q1
export ANGARABASE_TDE_LAST_ROTATION_UNIX=1760000000
| Variable | Purpose |
|---|---|
ANGARABASE_TDE_ENABLE | 1 to enable; unset or 0 to disable. |
ANGARABASE_TDE_MASTER_KEY_HEX | 256-bit key in hex (64 characters). Never appears in sys.settings or logs. |
ANGARABASE_TDE_MASTER_KEY_ID | Human-readable, non-secret key identifier (visible in sys.settings). |
ANGARABASE_TDE_LAST_ROTATION_UNIX | Unix timestamp of the last key rotation (metadata only). |
Fail-closed behaviour
- If
ANGARABASE_TDE_ENABLE=1and the key is missing, malformed, or wrong length, the server refuses to start. - If the key is invalid for the existing data directory, page/WAL decryption fails at startup — also fail-closed.
- The audit sink follows the same rule: without a valid key, audit read/write is impossible.
Verify from SQL
SELECT name, value
FROM sys.settings
WHERE name IN (
'security.tde_enabled',
'security.tde_master_key_id'
)
ORDER BY name;
Only non-secret metadata (key_id, enabled flag) is exposed. The hex key itself never appears.
Client-encrypted columns
Client-encrypted columns allow applications to store ciphertext in the database while the server never holds key material.
SQL surface
ALTER TABLE customers
ALTER COLUMN tax_id
SET ENCRYPTED WITH (TYPE=DETERMINISTIC, KEY_ID='cust-key-01');
Full syntax:
ALTER TABLE <table>
ALTER COLUMN <column>
SET ENCRYPTED WITH (
TYPE = DETERMINISTIC | RANDOMIZED,
KEY_ID = '<opaque-id>',
ALG = '<algorithm-id>' -- optional, defaults to AES-256-SIV / AES-256-GCM
);
What the server stores
| Field | Content |
|---|---|
enc.alg | Algorithm identifier (whitelisted). |
enc.mode | deterministic or randomized. |
enc.key_id | Opaque, non-secret key identifier. |
| payload | Ciphertext bytes — never interpreted by the server. |
The server never accepts raw key material via SQL, environment variables, config, logs, or sys.* views.
Operator rules
| Mode | Allowed operations | Rejected operations |
|---|---|---|
DETERMINISTIC | Equality predicates (=, !=, IN) | Range, LIKE, aggregation, ordering |
RANDOMIZED | None (read/write only) | All server-side predicates |
Unsupported operations return 0A000 feature_not_supported (shape-stable error).
Fail-closed and observability
- Missing or invalid encryption metadata on a column causes DML to be rejected.
sys.settingsand diagnostics expose onlykey_id, mode, and algorithm — never ciphertext blobs or key-like material.- Error messages never include ciphertext fragments or key material.
Expected result
- With TDE enabled, the data directory contains no plaintext data, WAL, or audit payloads.
sys.settingsshowssecurity.tde_enabled = trueand thekey_idwithout exposing the key.- Client-encrypted columns store ciphertext; deterministic mode allows equality queries; randomized mode rejects server-side predicates.
- All fail-closed paths produce deterministic errors, not silent fallbacks.
Troubleshooting
- Server refuses to start after enabling TDE
Check
ANGARABASE_TDE_MASTER_KEY_HEX— must be exactly 64 hex characters. If the data directory was previously unencrypted, you cannot enable TDE retroactively on existing data (see migration docs). 0A000 feature_not_supportedon encrypted column query The query uses an unsupported operator for the column’s encryption mode. ForRANDOMIZEDcolumns, only read/write is allowed. ForDETERMINISTIC, only equality predicates work.- Audit read/write fails with TDE enabled The audit DEK derives from the master key. Verify the master key matches the one used when the audit file was created.
sys.settingsdoes not show TDE knobs EnsureANGARABASE_TDE_ENABLE=1is set in the environment before server startup.- Need a bug-report artifact? See ../reference/support.md.
Links
- Security model overview: overview.md
- Audit (TDE interaction): audit.md
- Hardening runbook: hardening.md
- Configuration reference: ../operations/configuration.md
- Security knobs registry:
angarabook/src/operations/security-operations.md
Break-glass
Goal
Understand and use controlled privilege escalation (break-glass) to temporarily bypass RLS policies with full auditability.
Prerequisites
- SQL session with a user who has been granted the
BREAK_GLASScapability. - A healthy audit subsystem (break-glass cannot activate if audit is unavailable).
What is break-glass?
Break-glass is AngaraBase’s mechanism for controlled, time-limited, fully audited bypass of row-level
security policies. It exists because SUPERUSER alone does not bypass RLS — this is a deliberate design
choice.
Key properties:
- Activation requires a mandatory reason and a mandatory TTL.
- Every query executed during break-glass generates a dedicated
break_glass_queryaudit entry. - There is no “silent” bypass — the audit chain always records break-glass activity.
- This is a first-in-class database feature: neither PostgreSQL nor MS SQL Server have a built-in break-glass mechanism with TTL + reason + mandatory audit.
Steps
1) Grant the break-glass capability
A SECURITY_ADMIN grants the BREAK_GLASS role to a user or role:
GRANT BREAK_GLASS TO dba_team;
2) Activate break-glass
The user who has been granted BREAK_GLASS activates it with a reason and duration:
SET BREAK_GLASS REASON='INCIDENT-789: data corruption investigation' TTL='2h';
Duration format: '15m', '2h', '1d' etc. Maximum TTL is controlled by the server configuration (see
below).
3) Check status
SELECT * FROM angara_break_glass_status();
Returns: is_active, reason, expires_at, activated_at.
4) Work under break-glass
While break-glass is active, RLS policies are bypassed. Every query in this session generates an audit
entry with event_type = 'break_glass_query', including the full (sanitized) SQL text.
5) Deactivate (manual or automatic)
RESET BREAK_GLASS;
If not deactivated manually, break-glass auto-expires when the TTL elapses. After expiry, RLS applies again immediately.
6) Revoke the capability
REVOKE BREAK_GLASS FROM dba_team;
Configuration
| Variable | Default | Description |
|---|---|---|
ANGARABASE_SECURITY_BREAK_GLASS_MAX_TTL | 24h | Maximum allowed TTL for any break-glass session. Requests exceeding this are rejected. |
Also exposed as security.break_glass_max_ttl in sys.settings.
Audit trail
All break-glass lifecycle events are recorded:
| Event type | When |
|---|---|
break_glass_activate | SET BREAK_GLASS succeeds. |
break_glass_query | Every query while break-glass is active. |
break_glass_deactivate | RESET BREAK_GLASS is called. |
break_glass_expire | TTL elapses without manual deactivation. |
Invariants
- Audit must be healthy. If the audit subsystem is down or corrupted, break-glass activation fails (fail-closed).
- TTL is mandatory.
SET BREAK_GLASSwithoutTTL→ error. - Reason is mandatory.
SET BREAK_GLASSwithoutREASON→ error. - Max TTL is server-enforced. Exceeding
security.break_glass_max_ttl→22023 invalid_parameter_value. - No refresh. A client cannot extend the TTL — deactivate and re-activate with a new reason/TTL instead.
- SUPERUSER ≠ RLS bypass. Only
BREAK_GLASSbypasses RLS.
Expected result
SET BREAK_GLASSwith valid reason and TTL activates bypass;angara_break_glass_status()confirms.- All queries during break-glass appear in
sys.audit_logwithevent_type = 'break_glass_query'. - After TTL expiry or
RESET BREAK_GLASS, RLS enforcement resumes. - Invalid TTL returns
22023; missing reason or TTL returns an error.
Troubleshooting
22023 invalid_parameter_valueonSET BREAK_GLASSThe TTL exceedssecurity.break_glass_max_ttlor is in an invalid format. Check the max TTL setting and use a supported duration format ('15m','2h','1d').42501 insufficient_privilegeonSET BREAK_GLASSThe current user has not been grantedBREAK_GLASS. ASECURITY_ADMINmust runGRANT BREAK_GLASS TO <user>.- Break-glass activation fails with “audit unavailable”
The audit subsystem must be healthy. Check
ANGARABASE_AUDIT_LOG_PATHand audit key material if TDE is enabled. - Break-glass expired unexpectedly TTL is server-enforced and cannot be refreshed. Deactivate and re-activate with a new reason and TTL.
- Need a bug-report artifact? See ../reference/support.md.
Links
- Security model overview: overview.md
- Authorization (RLS policies): authorization.md
- Audit: audit.md
- Known issues: ../reference/known-issues.md
Deployment hardening runbook
Goal
Walk through a step-by-step process to launch AngaraBase in a production-secure configuration, and verify the result from SQL.
Prerequisites
- Access to server configuration (TOML config and/or environment variables).
- TLS certificate and key files.
- A 256-bit master key (64 hex characters) for TDE.
- Ability to restart the server.
Security hardening checklist
Before starting, confirm each item applies to your deployment:
- TLS enabled for all remote connectivity.
- Auth mode set explicitly (
scramorcert) — not left astrustfor production. - TDE enabled with valid key material.
- Audit log path set and writable.
- DML audit policy chosen deliberately (
off,allowlist, ordenylist). - Break-glass max TTL configured appropriately.
-
angara_audit_verify_chain()runs clean.
Steps
Step 1 — Enable TLS
[tls]
enabled = true
cert_path = "/etc/angarabase/tls/server.crt"
key_path = "/etc/angarabase/tls/server.key"
require_on_remote_bind = true
This protects the wire protocol and enforces fail-closed on non-loopback bind without TLS.
See authentication.md for TLS details.
Step 2 — Set auth mode
export ANGARABASE_AUTH_MODE=scram
Disables trust-only behaviour for production. The superuser must have been bootstrapped at --init time with
a SCRAM password.
See authentication.md for auth modes and SCRAM setup.
Step 3 — Enable TDE
export ANGARABASE_TDE_ENABLE=1
export ANGARABASE_TDE_MASTER_KEY_HEX=<64-hex-secret>
export ANGARABASE_TDE_MASTER_KEY_ID=master-prod-2026q1
export ANGARABASE_TDE_LAST_ROTATION_UNIX=1760000000
Enables at-rest encryption for pages, WAL, and audit sink. Without a valid key the server refuses to start (fail-closed).
See encryption.md for TDE configuration and key management.
Step 4 — Configure audit policy
export ANGARABASE_AUDIT_LOG_PATH=/var/lib/angarabase/audit/audit.jsonl
export ANGARABASE_AUDIT_DML_MODE=allowlist
export ANGARABASE_AUDIT_DML_ALLOWLIST=public.users,public.payments
export ANGARABASE_AUDIT_EXPORT_JSON_ENABLED=1
export ANGARABASE_AUDIT_EXPORT_RATE_LIMIT_RPS=50
Sets targeted DML audit coverage and bounded JSON export.
See audit.md for audit policy options and chain verification.
Step 5 — Verify effective config from SQL
After starting the server, confirm all settings from a SQL session:
SELECT name, value
FROM sys.settings
WHERE name IN (
'tls.enabled',
'tls.require_on_remote_bind',
'security.auth_mode',
'security.tde_enabled',
'security.tde_master_key_id',
'audit.dml_mode',
'audit.export_json_enabled',
'audit.export_rate_limit_rps'
)
ORDER BY name;
Only non-secret metadata appears. The TDE hex key, passwords, and SCRAM verifiers are never exposed.
Step 6 — Verify audit chain
SELECT * FROM angara_audit_verify_chain();
A healthy deployment returns is_valid = true.
Step 7 — Verify security surfaces
SELECT * FROM angara_user_roles() LIMIT 20;
SELECT * FROM angara_break_glass_status();
Confirm that introspection functions are responsive and return expected data.
Expected result
- Server starts only in fail-closed mode for unsafe configurations.
sys.settingsshows only non-secret metadata.- Disk contains no plaintext audit payloads when TDE is enabled.
- Audit chain is intact; DML events appear for tables in the allowlist.
- Authentication rejects unauthenticated connections in
scram/certmode.
Troubleshooting
- Server does not start after enabling TDE
Verify
ANGARABASE_TDE_MASTER_KEY_HEXis exactly 64 hex characters and matches the data directory’s key. Fail-closed is expected. - Auth/TLS conflict on remote bind
If binding to a non-loopback address,
tls.enabledmust betrueor--allow-insecure-no-authmust be passed (dev only). Checktls.require_on_remote_bindandserver.host. - DML audit events missing
Verify
audit.dml_modeis notoffand that the target table matches the allowlist/denylist entries. Table names must be fully qualified (schema.table). angara_audit_verify_chain()returnsis_valid = falseThe audit chain is corrupted. Note thefirst_broken_seqand investigate the audit file.- Break-glass cannot activate The audit subsystem must be healthy. Fix the audit path or TDE key material first.
- Need a bug-report artifact? See ../reference/support.md.
Links
- Security model overview: overview.md
- Authentication: authentication.md
- Authorization: authorization.md
- Audit: audit.md
- Encryption: encryption.md
- Break-glass: break-glass.md
- Configuration reference: ../operations/configuration.md
- Security knobs registry:
angarabook/src/operations/security-operations.md
GOST Security Compliance & Testing Guide
Status: TLS implemented, TDE planned Target Audience: Security Auditors, DevOps, QA
1. GOST Security Ecosystem in AngaraBase
AngaraBase implements a layered approach to Russian national cryptographic standards (GOST).
1.1. Transport Layer (TLS) — Available
Protection of data in transit using GOST R 34.10-2012 (Public Key) and GOST 28147-89 (Cipher suites).
- Implementation: Provider-based abstraction (OpenSSL Engine / Rustls).
- Policy: Fail-closed (server refuses to start if configured GOST provider is missing).
- Configuration:
tls.gost_enabled,tls.gost_cipher_suites.
1.2. Data-at-Rest (TDE) — Planned
Protection of data on disk (Pages, WAL, Audit Logs) using block ciphers Kuznyechik (GOST 34.12-2015) or Magma.
- Scope: Transparent Data Encryption (TDE) for storage files.
- Key Management: Integration with external KMS supporting GOST keys.
- Status: Roadmap item.
1.3. Integrity & Authentication — Future
- Hashing: Migration from SHA-256 to Streebog (GOST R 34.11-2012) for data checksums and SCRAM authentication.
- Audit Signing: Digital signature of audit logs to ensure non-repudiation.
2. Testing GOST TLS Support
This guide describes how to verify that AngaraBase is correctly using GOST cipher suites and strictly enforcing the fail-closed policy.
Prerequisites
You need a Linux environment with OpenSSL configured for GOST.
# Debian/Ubuntu
sudo apt-get install openssl libssl-dev libengines-gost
# Verify engine availability
openssl engine gost -t
# Output should contain: [gost] Reference implementation of GOST engine -> [ available ]
Step 1: Generate GOST Certificates
Standard RSA/ECDSA certificates will not work with GOST cipher suites. You must generate keys using GOST algorithms.
# 1. Generate a private key using GOST R 34.10-2012 (256 bit)
openssl genpkey -algorithm gost2012_256 -pkeyopt paramset:A -out gost_server.key
# 2. Generate a self-signed certificate
openssl req -new -x509 -days 365 \
-key gost_server.key \
-out gost_server.crt \
-subj "/CN=localhost"
# 3. Verify the certificate algorithm
openssl x509 -in gost_server.crt -text -noout | grep "Signature Algorithm"
# Expected: Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)
Step 2: Configure AngaraBase
Enable TLS and GOST mode. Ensure allow_insecure is OFF to test strict mode.
export ANGARABASE_TLS_ENABLE=1
export ANGARABASE_TLS_CERT_PATH=$(pwd)/gost_server.crt
export ANGARABASE_TLS_KEY_PATH=$(pwd)/gost_server.key
export ANGARABASE_TLS_GOST_ENABLED=1
export ANGARABASE_TLS_GOST_CIPHER_SUITES="GOST2012-GOST8912-GOST8912"
# Start the server
./angarabase-server
Step 3: Verification (Positive Test)
Connect using a client that supports GOST (e.g., openssl s_client or a patched psql).
Using OpenSSL s_client:
openssl s_client -connect localhost:5152 -servername localhost
Verification Checklist:
- Look for
Cipher : GOST2012-GOST8912-GOST8912(or similar GOST suite) in the output. - Look for
Protocol : TLSv1.2. - Ensure the handshake completes successfully.
Using SQL (if psql supports it):
SELECT name, value FROM sys.settings WHERE name LIKE 'tls.%';
-- Verify tls.gost_enabled is 'true'
Step 4: Fail-Closed Verification (Negative Test)
Verify that the server refuses to start if the environment is broken.
- Scenario A: Missing Provider.
Temporarily disable the GOST engine (e.g., by renaming the library or changing OpenSSL config) and try to
start AngaraBase with
ANGARABASE_TLS_GOST_ENABLED=1.
- Expected Result: Server panic/exit with “GOST provider not available”.
- Scenario B: Invalid Cipher Suite.
Set
ANGARABASE_TLS_GOST_CIPHER_SUITES="INVALID-CIPHER".
- Expected Result: Server panic/exit with configuration error.
- Scenario C: RSA Certificate with GOST Ciphers.
Try to start with
ANGARABASE_TLS_GOST_ENABLED=1but provide standard RSA certificates.
- Expected Result: Handshake failures (OpenSSL error: “no shared cipher” or “wrong signature type”).
3. Troubleshooting
| Symptom | Probable Cause | Fix |
|---|---|---|
no shared cipher | Client does not support GOST or Server has RSA certs. | Install libengines-gost on client; Use GOST certs on server. |
wrong signature type | Certificate key type mismatch. | Ensure gost2012_256 is used for key generation. |
| Server fails to start | openssl.cnf not configured for GOST. | Run openssl engine gost -t to verify system setup. |
Дальше
После того как вы определились, какие GOST-сценарии вам нужны:
- GOST crypto setup — пошаговая установка криптопровайдера и переключение профиля.
- Шифрование (TDE + клиентское) — общий контракт TDE и клиентского шифрования.
- Аудит — как замкнуть GOST-подписи на audit-chain.
- Hardening runbook — финальный чек-лист перед production.
Установка
AngaraBase распространяется через пакетные репозитории. Публичный доступ предоставляется бесплатно и без регистрации.
Поддерживаемые ОС
- RHEL-совместимые (8+): Red Hat Enterprise Linux, CentOS Stream, AlmaLinux, Rocky Linux, Oracle Linux, Fedora.
- Gentoo Linux: поддерживается через официальный binhost.
RPM (RHEL / CentOS / Alma / Fedora)
Установка производится через стандартный пакетный менеджер dnf.
1. Импорт GPG-ключа
Сначала необходимо импортировать публичный ключ, которым подписаны пакеты:
rpm --import https://rpm.angarabase.dev/release-key.asc
2. Подключение репозитория
Создайте файл конфигурации репозитория:
cat > /etc/yum.repos.d/angarabase.repo << 'EOF'
[angarabase]
name=AngaraBase
baseurl=https://rpm.angarabase.dev/el$releasever/stable/
enabled=1
gpgcheck=1
gpgkey=https://rpm.angarabase.dev/release-key.asc
EOF
3. Установка пакета
Установите серверный пакет:
dnf install angarabase-server
Gentoo Linux
Для Gentoo предоставляется готовый binhost со скомпилированными пакетами.
1. Импорт GPG-ключа
gpg --fetch-keys https://rpm.angarabase.dev/release-key.asc
2. Подключение binhost
Добавьте репозиторий в конфигурацию Portage:
cat >> /etc/portage/binrepos.conf << 'EOF'
[angarabase]
priority = 9999
sync-uri = https://rpm.angarabase.dev/gentoo/stable/
EOF
3. Установка пакета
Установите пакет, используя бинарную версию:
emerge --getbinpkg angarabase
Enterprise-репозиторий
Если у вас есть enterprise-подписка, вы получаете доступ к закрытому репозиторию с бинарными сборками. Доступ защищён с помощью mTLS (взаимная аутентификация по сертификатам).
Инструкция по подключению к Enterprise-репозиторию предоставляется вместе с invitation code при оформлении подписки. Если вы клиент, но у вас нет инструкции, напишите нам на team@angarabase.com.
Подробнее: angarabase.dev/enterprise
Configuration
Goal
Configure a AngaraBase instance for local testing or production deployment using TOML config keys, data-directory conventions, and environment variable overrides.
Prerequisites
- Built
angarabase-serverbinary (see Quickstart)
Minimal config keys
Server
[server]
addr = "127.0.0.1:5152" # host:port; use 0.0.0.0:PORT to bind all interfaces
Storage
[storage]
data_directory = "/var/lib/angarabase/data"
transaction_log_directory = "/var/lib/angarabase/txlog"
Logging
[logging]
log_level = "info"
log_directory = "/var/log/angarabase"
Ops (metrics / admin listeners)
[ops]
metrics_addr = "127.0.0.1:9898" # Prometheus metrics endpoint; empty = disabled
# admin_addr = "127.0.0.1:9999" # reserved, not yet active
Transaction log (durability)
[transaction_log]
backend = "noop"
durability = "strict"
fsync = true
TLS (optional)
[tls]
enabled = true
cert_path = "/etc/angarabase/tls/server.crt"
key_path = "/etc/angarabase/tls/server.key"
# If true and server.host is non-loopback, TLS is required (fail-closed).
require_on_remote_bind = true
WAL (Write-Ahead Log)
[wal]
vlf_enable = true
max_size_mb = 512
vlf_size_mb = 32
init_vlfs = 2
auto_shrink = true
SQL Execution
[execution]
mode = "auto" # auto | force_vector | force_row
vector_batch_size = 1024
query_memory_limit_mb = 256
Adaptive Query Processing (AQP)
[aqp]
enabled = true
mode = "conservative" # conservative | aggressive
min_query_time_ms = 100
learning_rate = 0.1
max_correction = 100.0
variance_threshold = 10.0
correction_cache_mb = 64
store_capacity_mb = 1024
Diagnostics
[diagnostics]
log_min_duration_ms = -1 # -1 = disabled
log_query_text = false
stat_statements_max = 0 # 0 = disabled
Initialization workflow
Run --init before the first normal start:
angarabase-server --config /path/to/angarabase.conf --init
- Directories
data_directoryandtransaction_log_directorymust be writable. - When a valid
logging.log_directoryis set, the server writesangarabase-server.log. --initcreates all required data-directory artifacts (see below).
For local dev/test shortcuts see Quickstart.
Data directory artifacts
Inside storage.data_directory the server creates and maintains:
| Artifact | Purpose |
|---|---|
VERSION | Initialization marker (format_version, min_server_version); enforces fail-closed startup. |
base.adb | On-disk system database file. |
Legacy text artifacts (identity_v0.txt, sys_catalog/*.txt) are no longer the source of truth and are not
created by --init. If they remain from older versions they are ignored.
Environment variables
Environment variables override the corresponding config keys. When both are set, the env variable wins.
Precedence rule: default → config → env override
All parameters can be configured in angarabase.conf. Environment variables are intended for operational
override without restart (for dynamic parameters) or for diagnostics. For permanent configuration, use the
TOML config file.
Core server knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_SHUTDOWN_TIMEOUT_MS | 1000 | Bounded graceful-shutdown timeout (ms). |
ANGARABASE_ALLOW_SQL_SHUTDOWN | off | Allow shutdown trigger via SELECT sys.request_shutdown(). |
ANGARABASE_STORAGE_STRICT_STARTUP | enabled | Storage verification on startup. Set 0/false/off to disable. |
ANGARABASE_METRICS_ADDR | — | Override for [ops].metrics_addr. |
ANGARABASE_SUPPORT_CONTACT | https://github.com/angarabase/angarabase/issues | Support contact shown by linux-gnu glibc compatibility guard when runtime glibc < 2.28. Override only if you run a forked distribution with its own support channel. |
ANGARABASE_IN_MEMORY_MAX_ROWS_PER_TABLE | 100000 | Default hard cap for storage='memory' tables when max_rows is omitted. Must be positive. |
TLS knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_TLS_ENABLE | off | Enable TLS upgrade via pgwire SSLRequest. |
ANGARABASE_TLS_CERT_PATH | — | PEM certificate chain (required when TLS enabled). |
ANGARABASE_TLS_KEY_PATH | — | PEM private key (required when TLS enabled). |
Transaction log knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_TRANSACTION_LOG | — | Override txlog backend (noop / file / file_bin). |
ANGARABASE_TRANSACTION_LOG_DURABILITY | — | Override durability (strict / relaxed / group_commit). |
ANGARABASE_TRANSACTION_LOG_FSYNC | — | Override fsync for strict mode (0 / 1). |
WAL (Write-Ahead Log) knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_WAL_VLF_ENABLE | enabled | Enable VLF (Virtual Log Files) circular layout. Set 0 to disable and use linear WAL. |
ANGARABASE_WAL_MAX_SIZE_MB | 512 | Maximum WAL file size in MB. Controls circular buffer size for VLF. |
ANGARABASE_WAL_VLF_SIZE_MB | 32 | Individual VLF segment size in MB. Must be smaller than WAL_MAX_SIZE_MB. |
ANGARABASE_WAL_INIT_VLFS | 2 | Initial number of VLF segments to allocate at startup. |
ANGARABASE_WAL_AUTO_SHRINK | enabled | Automatically shrink unused VLF segments after checkpoint. Set 0 to disable. |
Diagnostics / slow-query knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_LOG_MIN_DURATION_MS | -1 (disabled) | Slow-query log threshold in milliseconds. |
ANGARABASE_LOG_QUERY_TEXT | 0 | Include raw SQL text in slow log (0 / 1). |
ANGARABASE_STAT_STATEMENTS_MAX | — | Max in-memory entries for angara_stat_statements (LRU bounded). |
Optimizer planning knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_OPTIMIZER_PLANNING_TIMEOUT_MS | 0 | CBO planning budget in milliseconds (0 = disabled). On timeout the planner degrades to a greedy fallback plan instead of returning an error. |
sql.optimizer.planning_timeout_ms | 0 | Settings surface alias for optimizer planning timeout; reflected in sys.settings when configured. |
Vector execution knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_SQL_EXECUTION_MODE | auto | Execution mode for SELECT pipeline: auto (default, vector only when fully supported), force_vector (fail-closed if vector path is unavailable), force_row (always row engine). Legacy aliases vector and vector_auto remain accepted for compatibility. |
ANGARABASE_VECTOR_BATCH_SIZE | 1024 | Vector batch size (1..1024), mostly useful for tests and diagnostics. |
ANGARABASE_QUERY_MEMORY_LIMIT_MB | 256 | Per-query vector memory budget; exceeding the limit fails closed with SQLSTATE 53100 (no OOM fallback). |
Parallel execution governance knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_PARALLEL_DOP_CAP_GLOBAL | CPU cores | Global upper bound for SQL parallel workers. |
ANGARABASE_PARALLEL_DOP_CAP_QUERY | CPU cores | Per-query upper bound for SQL parallel workers. Effective DOP is capped by both values. |
Adaptive query processing knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_AQP_ENABLED | 1 | Global AQP switch for advisory feedback learning/apply. |
ANGARABASE_AQP_MODE | conservative | AQP mode (conservative / aggressive); conservative keeps correction hysteresis. |
ANGARABASE_AQP_MIN_QUERY_TIME_MS | 100 | Minimum query runtime eligible for feedback observation. |
ANGARABASE_AQP_LEARNING_RATE | 0.1 | EMA learning rate used for correction updates. |
ANGARABASE_AQP_MAX_CORRECTION | 100.0 | Upper correction multiplier bound (guardrail against outliers). |
ANGARABASE_AQP_VARIANCE_THRESHOLD | 10.0 | If variance exceeds threshold, correction entry is marked unstable and ignored. |
ANGARABASE_AQP_CORRECTION_CACHE_MB | 64 | In-memory correction cache budget. |
ANGARABASE_AQP_STORE_CAPACITY_MB | 1024 | Total bounded advisory store capacity; overflow evicts deterministic low-value entries. |
OpenTelemetry tracing knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_OTEL_ENABLED | 0 | Enable OTel-style query span export (0 / 1). |
ANGARABASE_OTEL_SAMPLE_RATE_PPM | 1000000 | Sampling in parts-per-million (0..1000000). |
ANGARABASE_OTEL_EXPORTER | stderr | Export sink (stderr / file). |
ANGARABASE_OTEL_ENDPOINT | — | Export target for file exporter (JSONL path). |
See also Diagnostics for query performance analysis.
Authentication knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_AUTH_MODE | — | Auth mode contract (trust / scram / cert). |
Startup safety: trust/no-auth mode now requires explicit --allow-insecure-no-auth; without this flag the
server refuses to start when ANGARABASE_AUTH_MODE resolves to trust/no-auth.
Security / break-glass knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_SECURITY_BREAK_GLASS_MAX_TTL | 86400 | Max allowed break-glass TTL in seconds. |
Audit knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_AUDIT_LOG_PATH | — | Path to append-only audit sink file (JSONL + chain-hash fields). |
ANGARABASE_AUDIT_MAX_BYTES | 4194304 (4 MiB) | Rotation threshold for audit sink. |
ANGARABASE_AUDIT_DML_MODE | off | Audit policy for DML (off / allowlist / denylist). |
ANGARABASE_AUDIT_DML_ALLOWLIST | — | CSV schema.table list for audited DML (allowlist mode). |
ANGARABASE_AUDIT_DML_DENYLIST | — | CSV schema.table list excluded from audit (denylist mode). |
ANGARABASE_AUDIT_EXPORT_JSON_ENABLED | 0 | Enable JSON export worker. |
ANGARABASE_AUDIT_EXPORT_SYSLOG_ENABLED | 0 | Enable syslog export worker. |
ANGARABASE_AUDIT_EXPORT_RATE_LIMIT_RPS | — | Export rate limit in records/second (bounded). |
AngaraIO v2 I/O Scheduler knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_IO_URING_QUEUE_DEPTH_LOW | entries/4 | Low-priority I/O queue depth. Controls backpressure for non-critical operations. Clamped to 1–16384. |
ANGARABASE_IO_URING_BATCH_MAX | 16 | Maximum I/O operations batched per scheduler round. Higher values improve throughput but increase latency. Clamped to 1–1024. |
Note: High-priority queue is unbounded per RFC invariant to ensure critical operations never block.
TDE (Transparent Data Encryption) knobs
| Variable | Default | Description |
|---|---|---|
ANGARABASE_TDE_ENABLE | 0 | Enable TDE v0 for page/WAL at-rest encryption. |
ANGARABASE_TDE_MASTER_KEY_HEX | — | Master key bytes in hex (64 chars; secret; required when TDE enabled). |
ANGARABASE_TDE_MASTER_KEY_ID | — | Non-secret key identifier visible in sys.settings. |
ANGARABASE_TDE_LAST_ROTATION_UNIX | — | Non-secret last-rotation timestamp visible in sys.settings. |
Security note: when ANGARABASE_TDE_ENABLE=1 and ANGARABASE_AUDIT_LOG_PATH is set, the audit sink is
encrypted at rest; without valid key material audit read/write is fail-closed (no plaintext fallback).
Expected result
After a successful --init and start:
curl -sS http://127.0.0.1:9898/health/ready # порт совпадает с [ops].metrics_addr
Returns {"status":"ready"}. Effective configuration is visible via:
SELECT * FROM sys.settings;
Troubleshooting
| Symptom | Action |
|---|---|
| Server refuses to start in trust mode | Add --allow-insecure-no-auth. |
VERSION mismatch at startup | The data directory was initialized by a different server version. Re-init or upgrade. |
| TDE fail-closed after restore | Ensure the same key material (ANGARABASE_TDE_MASTER_KEY_HEX) is available. |
| Parameter not applied | Check precedence: env variables override config. Use SELECT * FROM sys.settings to see effective values and sources. |
For unresolved issues see Known issues and Support.
Links
- Security/ops knobs registry (full defaults, fail-closed gates,
sys.settingscontract):angarabook/src/operations/security-operations.md - Operator runbook:
angarabook/src/operations/troubleshooting.md - Security overview: Security model
- Quickstart: Quickstart
Container Deployment Quickstart
Операторский quickstart для image-first запуска AngaraBase:
- локальный
docker runс cgroup-aware startup probe; - минимальный k8s deployment (
single-node, без HA); - smoke-проверки readiness и базовой диагностики.
0) 30-second evaluator path (image-only)
Если нужен быстрый evaluator/DPP smoke без Rust toolchain:
tools/compat_suite/image_smoke.sh
Скрипт поднимает контейнер из канонического Dockerfile, ждёт /health/ready,
проверяет startup log (deployment probe resolved effective budgets, cgroup_version)
и наличие probe-метрик в /metrics.
1) Local container smoke (docker run)
Сборка образа:
docker build -t angarabase:local .
Запуск с memory limit (контракт probe-а):
docker run --rm --name angarabase-local \
--memory=512m \
-e ANGARABASE_DEPLOYMENT_PROFILE=container \
-p 5152:5152 \
-p 9898:9898 \
angarabase:local
Ожидаемый признак в логах:
- есть строка
deployment probe resolved effective budgets; deployment_profile=container;memory_source/cpu_sourceотражаютcgroup_v1илиcgroup_v2(либоproc_fallbackсfallback_reason).
Проверка readiness в контейнере:
curl -fsS http://127.0.0.1:9898/health/ready
HEALTHCHECK контейнера использует этот же endpoint, поэтому становится green только
после прохождения health_readiness_reason_v0().
Проверка метрик:
curl -fsS http://127.0.0.1:9898/metrics | rg "deployment_probe|deployment_profile"
2) Resource-limit examples
CPU + memory cap:
docker run --rm --name angarabase-capped \
--memory=1g \
--cpus=1.5 \
-e ANGARABASE_DEPLOYMENT_PROFILE=container \
-p 5152:5152 \
-p 9898:9898 \
angarabase:local
Explicit override (probe не должен перезаписать):
docker run --rm \
--memory=512m \
-e ANGARABASE_DEPLOYMENT_PROFILE=container \
-e ANGARABASE_MEMORY_BUDGET=256MB \
-e ANGARABASE_CPU_BUDGET=1000m \
-p 5152:5152 \
-p 9898:9898 \
angarabase:local
Ожидаемо: в метриках/логах источник budget-а становится config_override.
3) Kubernetes minimal smoke
Применение манифестов:
kubectl apply -f tools/deploy/kubernetes/minimal/namespace.yaml
kubectl apply -f tools/deploy/kubernetes/minimal/configmap.yaml
kubectl apply -f tools/deploy/kubernetes/minimal/service.yaml
kubectl apply -f tools/deploy/kubernetes/minimal/statefulset.yaml
Проверка:
kubectl -n angarabase get pods
kubectl -n angarabase get svc angarabase
kubectl -n angarabase logs statefulset/angarabase
kubectl -n angarabase get statefulset angarabase -o yaml | rg "resources:|health/"
Важно: в statefulset.yaml заданы resources.requests/limits. Если убрать лимиты,
probe может увидеть “unlimited” и перейти на host-level fallback для budget-ов.
Удаление:
kubectl delete namespace angarabase
4) Diagnostics and backup entrypoints
Для packaged/operator path используйте angara-cli вместо прямых вызовов tools/...:
angara-cli diagnostics bundle --root artifacts/diagnostics/container-smoke --json
angara-cli backup full --config /etc/angarabase/angarabase.conf --out /tmp/base_full.abk
Связанные runbooks:
DPP alignment:
- safety rails по ресурсным лимитам и fail-closed режиму см.
business_strategy/PILOT_CHECKLIST.md(§5 и §6).
Backup and restore
Goal
Create and restore backups of a AngaraBase instance — from cold/offline baselines through online FULL + LOG chain with point-in-time recovery (PITR).
Prerequisites
- Initialized AngaraBase instance (
angarabase-server --init; see Configuration) - Built
angara-clibinary (see Quickstart) - For online backups (phase 1b): a running server with WAL (
transaction_logbackend ≠noop)
Cold / offline backup
The original supported method. The server must be stopped (or will be stopped by the runner).
- Copy
storage.data_directoryandstorage.transaction_log_directory. - After restore, run the txlog-level oracle.
- The source must be a correctly initialized data directory.
Pinned commands (legacy shell)
Backup:
tools/backup_restore/run.sh backup \
--data-dir /var/lib/angarabase/data \
--txlog-dir /var/lib/angarabase/transaction_log \
--out /tmp/angarabase-backup.tar.gz \
--root artifacts/backup_restore/backup
Restore:
tools/backup_restore/run.sh restore \
--archive /tmp/angarabase-backup.tar.gz \
--dest /tmp/angarabase-restore \
--force \
--root artifacts/backup_restore/restore
Oracle (post-restore verification):
tools/backup_restore/oracle.sh --root artifacts/backup_restore_oracle/run_1
Remote Admin Backup Flow (Online Backup via Admin API)
AngaraBase supports triggering backups remotely via the Admin TCP endpoint. This is the recommended approach for production deployments, as it does not require direct file system access to the database node.
Requirements
- The
angarabase-servermust be running with the Admin API enabled (configured viaadmin.listen_addressinangarabase.conforANGARABASE_ADMIN_ADDRenvironment variable). angara-climust be executed with the--addr <host:port>parameter instead of--config.- The user executing the backup must have network access to the Admin API port (default:
9899).
How it works
When using --addr, angara-cli connects to the running server’s Admin API and issues a RUN backup_full
command. The server coordinates the backup process internally (Fuzzy Copy, WAL Inclusion) and streams the
resulting .angarabk file back to the client over the network.
This allows operators to take backups from a central management node without SSH access to the database servers.
Storage layout note
User tables use the page-based .adb path. Legacy heap_store/*.bin is migrated to .adb on first access.
For backup/restore and triage:
- Both files per database are critical:
<db>.adband<db>.atl. heap_store/is not the source of truth after migration.- Upgrading old instances may take time proportional to
heap_storevolume. - If the backup was taken with TDE enabled (
ANGARABASE_TDE_ENABLE=1), restore requires the same valid key material; without it, startup after restore is fail-closed.
Backup/Restore v2 — phase 1a: one-file backupset
Minimal offline pipeline producing a single *.angarabk file (manifest-first format).
Capabilities
| Command | Purpose |
|---|---|
backup full | Offline FULL backup to a single file. |
backup inspect | Read manifest only (no payload scan). |
backup verify | Struct/hash integrity check (binary answer). |
backup restore | Local restore + txlog-level oracle (best-effort). |
Pinned commands (phase 1a)
# FULL (offline/local baseline)
angara-cli backup full \
--config /path/to/angarabase.conf \
--out /tmp/full_0001.angarabk \
--db-id base
# FULL (remote execution via Admin API)
angara-cli backup full \
--addr 127.0.0.1:9899 \
--out /tmp/full_0001.angarabk \
--db-id base
# INSPECT (manifest-only)
angara-cli backup inspect --file /tmp/full_0001.angarabk
# VERIFY v0 (struct/hash)
angara-cli backup verify --file /tmp/full_0001.angarabk --json
# RESTORE (local) into a new directory
angara-cli backup restore \
--config /path/to/angarabase.conf \
--file /tmp/full_0001.angarabk \
--target-dir /tmp/restore_0001 \
--overwrite
Evidence pack (N=3)
tools/backup_restore/evidence_v2_phase1a.sh --runs 3
Inspect vs verify
backup inspect: manifest-only, no payload scan.backup verify: struct/hash integrity; proves backupset consistency, not SQL-level correctness.
Backup/Restore v2 — phase 1b: online FULL + LOG chain + PITR
Online pipeline with point-in-time recovery support.
Capabilities
| Command | Purpose |
|---|---|
backup full-online | Online FULL boundary (best-effort, with backup fence). |
backup log | WAL chunk by LSN range (strictly contiguous chain). |
backup chain-validate | Binary validation of the full chain. |
backup restore-chain | PITR restore to target_lsn + oracle. |
Pinned commands (phase 1b)
# ONLINE FULL (best-effort, with backup fence)
# Local execution:
angara-cli backup full-online \
--config /path/to/angarabase.conf \
--out /tmp/full_online_0001.angarabk \
--db-id base
# Remote execution (via Admin API):
angara-cli backup full-online \
--addr 127.0.0.1:9899 \
--out /tmp/full_online_0001.angarabk \
--db-id base
# LOG chunk (LSN boundaries must be contiguous with FULL/prev LOG)
angara-cli backup log \
--config /path/to/angarabase.conf \
--out /tmp/log_0001.angarabk \
--start-lsn <u64> --end-lsn <u64> \
--db-id base
# Validate chain contiguity
angara-cli backup chain-validate \
--chain /tmp/full_online_0001.angarabk,/tmp/log_0001.angarabk \
--json
# PITR restore to target_lsn
angara-cli backup restore-chain \
--config /path/to/angarabase.conf \
--target-dir /tmp/restore_chain_0001 \
--target-lsn <u64> \
--chain /tmp/full_online_0001.angarabk,/tmp/log_0001.angarabk \
--overwrite
Evidence pack (N=3)
tools/backup_restore/evidence_v2_phase1b.sh --runs 3
Expected result
After a successful restore the server should start cleanly and previously committed data should be present:
SELECT * FROM sys.health;
SELECT * FROM sys.identity;
For PITR restores, data reflects the state at target_lsn.
Troubleshooting
| Symptom | Action |
|---|---|
| Restore fails with TDE error | Ensure the same ANGARABASE_TDE_MASTER_KEY_HEX is set. See Configuration — TDE knobs. |
| Chain validation fails | LSN boundaries between FULL and LOG chunks must be contiguous. Re-take the LOG chunk from the correct start LSN. |
| Oracle reports mismatch | The txlog replay-pages oracle is best-effort. Collect artifacts and file a report via Support. |
heap_store migration slow after restore | Expected for legacy-format backups. Migration is proportional to heap_store size. |
For unresolved issues see Known issues and Support.
Host migration (без dump/restore)
Альтернатива backup/restore для переноса AngaraBase на другой хост — прямое копирование файлов данных с использованием Instance Lease системы.
Когда применимо
- Single-node deployment — один инстанс AngaraBase
- Shared storage — NFS, SAN или ручное копирование файлов
- Same version — одинаковая версия AngaraBase на источнике и цели
- Maintenance window — можно остановить инстанс на время копирования
Пошаговая инструкция
- Остановить source инстанс:
# Graceful shutdown для освобождения lease
kill -TERM <angarabase-pid>
# Дождаться завершения
ps aux | grep angarabase-server
- Проверить освобождение lease (опционально):
-- На другом инстансе или через backup connection
SELECT lease_holder_id FROM sys.identity;
- Скопировать файлы данных:
# Копировать data directory
rsync -av /source/data/ /target/data/
# Копировать transaction log directory
rsync -av /source/txlog/ /target/txlog/
# Проверить целостность
find /target/data -name "*.adb" -exec ls -la {} \;
- Запустить на target хосте:
# Обновить конфигурацию если нужно
vim /target/angarabase.conf
# Запустить AngaraBase
angarabase-server --config /target/angarabase.conf
- Проверить миграцию:
-- Проверить lease holder
SELECT lease_holder_hostname, recovery_mode FROM sys.identity;
-- Проверить целостность данных
SELECT COUNT(*) FROM your_tables;
-- Проверить состояние системы
SELECT * FROM sys.health;
Что проверить после старта
-
lease_holder_hostnameизменился на новый хост -
recovery_modeпоказывает тип восстановления - Все таблицы доступны и содержат ожидаемые данные
- Нет ошибок в логах сервера
- Клиентские подключения работают корректно
Ограничения
- Downtime required — требует остановки сервиса на время копирования
- File consistency — файлы должны быть скопированы атомарно
- Version compatibility — версии AngaraBase должны совпадать
- Configuration — пути в конфигурации могут потребовать обновления
Сравнение с backup/restore
| Аспект | Host migration | Backup/restore |
|---|---|---|
| Downtime | Время копирования файлов | Время backup + restore |
| Disk space | 1x (только target) | 2x (backup + target) |
| Network | Прямое копирование | Через backup storage |
| Complexity | Низкая | Средняя |
| Point-in-time | Только текущее состояние | Любой LSN |
См. также
Подробные инструкции по host migration: Crash Recovery — Host Migration
Links
-
Canonical operator runbook:
angarabook/src/operations/backup-restore.md -
Configuration reference: Configuration
-
Diagnostics (post-restore health check): Diagnostics
-
Host migration details: Crash Recovery
Crash Recovery and Storage Portability
This guide covers crash recovery scenarios and how to safely restart AngaraBase instances on existing data files, including migration to different hosts.
Overview
AngaraBase includes an Instance Lease system that prevents dual-write corruption while enabling safe crash recovery and storage portability. The system works on any filesystem, including NFS and SAN where traditional file locking is unreliable.
What Happens During Crash Recovery
When AngaraBase starts on existing data files, it performs these recovery phases:
Phase A: WAL Recovery (file_bin backend only)
- Scans transaction log files for incomplete entries
- Truncates partial tail records to maintain consistency
- Replays committed page deltas (redo operations)
Phase B: MVCC History Restore
- Recovers in-memory MVCC state from transaction log
- Marks uncommitted transactions as aborted
- Restores visibility information for concurrent reads
Phase C: Instance Lease Check
- Checks for active instance lease in
base.adb - Prevents dual instance startup with fail-closed error
- Automatically takes over expired leases (crash recovery)
Restarting on Existing Files (Same Host)
For normal restart scenarios on the same machine:
- Stop the server (if running):
# Graceful shutdown releases the lease automatically
kill -TERM <angarabase-pid>
- Start normally:
angarabase-server --config angarabase.conf
- Verify recovery:
SELECT recovery_mode, lease_holder_id FROM sys.identity;
The instance lease will be automatically acquired after the TTL expires (default: 30 seconds).
Host Migration (Without dump/restore)
To move data files to a different host:
Prerequisites
- Both hosts have the same AngaraBase version
- Same page size (checked automatically)
- Shared storage OR manual file copy
Step-by-Step Process
- Stop the source instance:
# Graceful shutdown to release lease
kill -TERM <angarabase-pid>
# Verify shutdown completed
ps aux | grep angarabase-server
- Verify lease is released:
# Check that no process holds the lease
# (Optional: use another AngaraBase instance to query sys.identity)
- Copy data files (if not using shared storage):
# Copy entire data directory
rsync -av /old/host/data/ /new/host/data/
# Copy transaction log directory
rsync -av /old/host/txlog/ /new/host/txlog/
- Start on new host:
angarabase-server --config angarabase.conf
- Verify migration:
SELECT lease_holder_hostname, recovery_mode FROM sys.identity;
SELECT COUNT(*) FROM your_tables; -- Verify data integrity
Force Lease Takeover
If the previous instance crashed and the lease hasn’t expired, use force takeover:
When to Use
- Previous instance confirmed dead (host crashed, process killed)
- Lease shows expired time but takeover not automatic
- Emergency recovery scenarios
How to Use
# Set environment variable before starting
export ANGARABASE_FORCE_LEASE_TAKEOVER=1
angarabase-server --config angarabase.conf
Safety Checks
Before forcing takeover, verify:
- Previous instance process is definitely terminated
- No other AngaraBase processes accessing the same files
- Network partitions resolved (if applicable)
Warning: Force takeover with a running instance will cause data corruption.
Diagnostics
Check Lease Status
SELECT
lease_holder_id,
lease_holder_hostname,
lease_expires_at,
lease_acquired_at,
recovery_mode
FROM sys.identity;
Check Recovery Metrics
SELECT * FROM sys.health;
Lease Configuration
Environment variables (set before startup):
ANGARABASE_LEASE_TTL_S: Lease duration in seconds (default: 30)ANGARABASE_LEASE_HEARTBEAT_S: Heartbeat interval (default: 10)ANGARABASE_FORCE_LEASE_TAKEOVER: Force takeover flag (default: false)
Limitations
WAL Backend Requirements
- Full recovery: Requires
transaction_log.backend = "file_bin" - Partial recovery:
noopbackend has no WAL replay (data loss possible)
Filesystem Considerations
- Local filesystems: Full support (ext4, xfs, btrfs, etc.)
- NFS/SAN: Instance lease works; verify file copy consistency
- Network partitions: May cause false lease expiration
Version Compatibility
- Same major.minor version required for host migration
- Page size must match (checked automatically)
- Configuration compatibility recommended
Troubleshooting
“Cannot start: database files are owned by another instance”
- Cause: Active lease held by another instance
- Solution: Wait for lease expiration or use force takeover (if safe)
“MVCC recovery failed”
- Cause: Corrupted transaction log files
- Solution: Check disk space, filesystem errors; may need backup restore
“VERSION decode failed”
- Cause: Corrupted version marker or incompatible format
- Solution: Restore from backup; check filesystem integrity
Performance After Recovery
- First queries may be slower (cold buffer pool)
- MVCC state rebuilds incrementally
- Statistics may need refresh (
ANALYZE TABLE)
See Also
- Instance Lifecycle - Conceptual overview
- Backup and Restore - Host migration alternatives
- Configuration - Lease settings reference
Обновление бинарного релиза
Этот сценарий покрывает upgrade/downgrade без изменения on-disk формата в рамках текущей релизной линии.
Инварианты
- Обновление меняет бинарники и unit/scripts, но не трогает пользовательские данные.
- Каталог данных
/var/lib/angarabaseне удаляется. - Конфиг
/etc/angarabase/angarabase.confсохраняется (noreplace-политика пакета).
Upgrade через DEB/RPM
DEB
sudo dpkg -i angarabase-server_<VERSION>_amd64.deb
sudo systemctl status angarabase --no-pager
RPM
sudo rpm -Uvh angarabase-server-<VERSION>-1.x86_64.rpm
sudo systemctl status angarabase --no-pager
Upgrade из tarball
sudo systemctl stop angarabase
sudo install -m 0755 bin/angarabase-server /usr/bin/angarabase-server
sudo install -m 0755 bin/angara-cli /usr/bin/angara-cli
sudo systemctl daemon-reload
sudo systemctl start angarabase
Проверка после обновления
angarabase-server --version
sudo systemctl is-active angarabase
Smoke-check:
- сервер поднимается без panic;
- конфиг и data dir доступны;
- базовый SQL health-check проходит.
Rollback
Rollback выполняется установкой предыдущего пакета/архива.
Важно: rollback допустим только между совместимыми версиями контрактов хранения.
Дальше
После успешного обновления и прохождения post-upgrade чек-листа:
- Crash recovery — что делать, если новая версия не стартанула.
- Резервное копирование и восстановление — снять контрольный backup сразу после апгрейда.
- Verify release artifacts — убедиться, что следующая версия скачана и проверена тем же способом.
- Operator deep-dive: Upgrade and migration — полный плейбук с rollback-сценариями.
Monitoring
Goal
Connect Prometheus and Grafana to AngaraBase metrics and get a working dashboard for ops/triage monitoring.
Prerequisites
- Running
angarabase-server(see Quickstart) - Access to the AngaraBase metrics listener (
ANGARABASE_METRICS_ADDR) - Running Prometheus instance
- Running Grafana instance
Step 1: enable the metrics endpoint
Set the listener address in the config file:
[ops]
metrics_addr = "127.0.0.1:9898"
Or use the environment variable override (takes precedence over config):
export ANGARABASE_METRICS_ADDR=127.0.0.1:9898
angarabase-server --config /etc/angarabase/angarabase.conf
Verify the endpoint responds:
curl -sS http://127.0.0.1:9898/metrics | rg '^angarabase_' -m 5
curl -sS http://127.0.0.1:9898/health/live
curl -sS http://127.0.0.1:9898/health/ready
curl -sS http://127.0.0.1:9898/health/startup
See Configuration — Ops knobs for the full [ops] section reference.
OpenTelemetry tracing
AngaraBase also exposes opt-in OTel-style span export for query lifecycle triage.
Minimal setup example:
export ANGARABASE_OTEL_ENABLED=1
export ANGARABASE_OTEL_EXPORTER=file
export ANGARABASE_OTEL_ENDPOINT=artifacts/otel/spans.jsonl
export ANGARABASE_OTEL_SAMPLE_RATE_PPM=1000000
Spans are emitted for bounded stage names (accept, auth, session, parse, plan, execute,
storage_io, commit/rollback) and are intended for diagnostics evidence, not for raw SQL capture.
Step 2: configure the Prometheus scrape
Add a job to prometheus.yml:
scrape_configs:
- job_name: angarabase
scrape_interval: 15s
metrics_path: /metrics
static_configs:
- targets: ["127.0.0.1:9898"]
Restart Prometheus and verify in the UI (/targets) that the angarabase target is UP.
Step 3: add the Prometheus data source in Grafana
- Open the Grafana UI.
- Navigate to Connections → Data sources.
- Add Prometheus.
- Set the URL to your Prometheus instance (e.g.,
http://127.0.0.1:9090). - Click Save & test and confirm the connection succeeds.
Step 4: import the AngaraBase dashboard
- Go to Dashboards → New → Import.
- Upload the file
tools/observability/grafana/angarabase-overview-v2.json. - Select the Prometheus data source added in the previous step.
- Save the dashboard.
Alternative — download the JSON directly from the server:
curl -fsS http://127.0.0.1:9898/grafana/angarabase-overview.json -o angarabase-overview.json
Then import angarabase-overview.json in Grafana.
Expected result
After import, the dashboard should display the following panels:
| Panel | Key metric(s) |
|---|---|
| QPS | angarabase_queries_total |
| Query latency p50/p95/p99 | histogram buckets |
| Slow query count | angarabase_slow_query_total |
| Active connections | gauge |
| TPS / commit latency | angarabase_commits_total |
| Lock contention | lock wait counters |
| Buffer pool pressure | angarabase_buffer_pool_hit_total, angarabase_buffer_pool_miss_total |
| BRIN range efficiency | angara_brin_range_efficiency |
| Mutation policy rejections | angara_table_no_delete_rejected_*, angara_table_mutation_epoch |
| WAL lag / fsync latency | WAL counters |
| IO latency / checkpoint / GC pressure | IO counters |
If panels are empty, see Troubleshooting below.
Troubleshooting
No data in panels
- Check
http://<prometheus>/targets: theangarabasetarget must beUP. - Ensure
ANGARABASE_METRICS_ADDRmatches thetargetsvalue in Prometheus. - Verify metrics use the
angarabase_prefix:
curl -sS http://127.0.0.1:9898/metrics | rg '^angarabase_' -m 20
Data source test fails in Grafana
- Verify the data source URL and network reachability from Grafana to Prometheus.
- For Docker/K8s use the service DNS/hostname (not
127.0.0.1) when Grafana and Prometheus run in different containers.
Readiness probe is not ready
GET /health/readyreturns a reason in JSON — this is the primary triage signal.- Collect a diagnostics bundle and attach
summary.json:
tools/diagnostics_bundle/run.sh \
--root artifacts/diagnostics/<incident-id> \
--config <path> \
--metrics-url http://<metrics-host>/metrics
- For further investigation see Diagnostics and Support.
Links
- Dashboard JSON:
tools/observability/grafana/angarabase-overview-v2.json - Dashboard JSON from server:
GET /grafana/angarabase-overview.json(onANGARABASE_METRICS_ADDR/[ops].metrics_addr) - Dashboard import guide:
tools/observability/README.md - Operator runbook (metrics + probes): Troubleshooting guide
- Metrics checklist (contract): Observability metrics checklist
- Configuration reference: Configuration
- Support flow: Support
Diagnostics
Goal
Analyze query performance, inspect server state, and triage issues using AngaraBase’s built-in diagnostic tools.
Prerequisites
- Running
angarabase-server(see Quickstart) psqlor another pgwire-compatible client- For slow-query logging: env variables set before server start (see Configuration)
EXPLAIN variants
Basic query plan
EXPLAIN SELECT * FROM t WHERE id = 1;
Shows the planned execution path without running the query.
EXPLAIN ANALYZE (with actual timing)
EXPLAIN ANALYZE SELECT * FROM t WHERE id > 100;
Executes the query and reports actual row counts and timing alongside the plan.
For parallel join plans, EXPLAIN ANALYZE also reports best-effort join accounting counters:
join_build_rows— rows processed by join build phase,join_probe_rows— rows processed by join probe phase.
EXPLAIN ANALYZE for DML (dry-run)
EXPLAIN ANALYZE over INSERT, UPDATE, or DELETE runs the statement inside an isolated dry-run
transaction that rolls back automatically — no data is modified.
EXPLAIN ANALYZE INSERT INTO t (id, v) VALUES (999, 42);
EXPLAIN ANALYZE UPDATE t SET v = v + 1 WHERE id = 1;
EXPLAIN ANALYZE DELETE FROM t WHERE id = 1;
Buffer statistics
EXPLAIN (BUFFERS) SELECT * FROM t WHERE id = 1;
Adds buffer-pool hit/miss counters to the plan output.
JSON output
EXPLAIN (FORMAT JSON) SELECT * FROM t WHERE id = 1;
Returns the plan as a JSON document — useful for programmatic analysis.
Runtime diagnostic views
angara_stat_activity
Shows currently executing queries and their wait state.
SELECT pid, state, wait_event_type, query
FROM angara_stat_activity;
wait_event_type values: Lock, IO, Net, CPU — provides coarse wait categorization for triage.
angara_stat_statements
Aggregated per-query statistics (call count, total time, rows, etc.).
SELECT query, calls, total_time, rows
FROM angara_stat_statements
ORDER BY total_time DESC
LIMIT 10;
Reset accumulated stats:
SELECT angara_stat_statements_reset();
The maximum number of tracked statements is controlled by ANGARABASE_STAT_STATEMENTS_MAX (LRU-bounded). See
Configuration — Diagnostics knobs.
angara_top_queries
Convenience wrapper returning the top-N queries by cumulative time:
SELECT * FROM angara_top_queries(10);
Slow-query log
Capture queries that exceed a duration threshold to the server log.
Configuration
Set before server start (env variables override config):
| Variable | Default | Description |
|---|---|---|
ANGARABASE_LOG_MIN_DURATION_MS | -1 (disabled) | Threshold in milliseconds. Set to 0 to log all queries. |
ANGARABASE_LOG_QUERY_TEXT | 0 | Include raw SQL text in the log entry (0 / 1). |
Example:
export ANGARABASE_LOG_MIN_DURATION_MS=500
export ANGARABASE_LOG_QUERY_TEXT=1
angarabase-server --config /path/to/angarabase.conf
Slow queries appear in the server log at logging.log_directory.
Saturation / backpressure (operability)
When p99/p99.9 degrades under load, you usually want to distinguish:
- lock/contention waits,
- IO/scheduler saturation,
- admission/queue rejects vs “random” timeouts.
Practical entry points:
angara_stat_activity.wait_event_type(coarse wait classification)- operator runbook:
angarabook/src/operations/troubleshooting.md
System introspection views
sys.health
Overall server health status:
SELECT * FROM sys.health;
sys.settings
Effective configuration (config + env overrides resolved):
SELECT * FROM sys.settings;
SELECT * FROM sys.settings WHERE name LIKE 'storage.%';
sys.identity
Instance identity metadata:
SELECT * FROM sys.identity;
Expected result
EXPLAINvariants return plan text (or JSON) without errors.angara_stat_activityshows at least the current session.angara_stat_statementsaccumulates entries after queries are executed.sys.healthreturns{"status":"ready"}on a healthy instance.
Troubleshooting
| Symptom | Action |
|---|---|
EXPLAIN ANALYZE modifies data | This should not happen — DML runs in a dry-run transaction. If data changes persist, file a bug via Support. |
angara_stat_statements is empty | Ensure queries have been executed since the last reset. Check ANGARABASE_STAT_STATEMENTS_MAX is not 0. |
| Slow-query log has no entries | Verify ANGARABASE_LOG_MIN_DURATION_MS is set to a non-negative value and queries actually exceed the threshold. |
sys.health shows not-ready | Check GET /health/ready for the JSON reason. Collect a diagnostics bundle — see Monitoring. |
For unresolved issues see Known issues and Support.
Links
- SQL compatibility reference: SQL overview
- Monitoring setup: Monitoring
- Configuration (env knobs): Configuration
- Diagnostics bundle tool:
tools/diagnostics_bundle/run.sh - Operator runbook:
angarabook/src/operations/troubleshooting.md - Инцидентный runbook (10 минут): Error debug runbook
- Support flow: Support
Structured Logging
Status: ✅ Active Scope: Production operations, diagnostics, troubleshooting
Overview
AngaraBase uses structured logging for production observability and diagnostics. This replaces ad-hoc
println! calls with consistent, level-based log messages using the Rust log crate and env_logger
backend.
Key Benefits
- Consistent Format: All log messages follow structured
key=valueformat - Level Control: Runtime-configurable verbosity (error/warn/info/debug/trace)
- Production Ready: Suitable for log aggregation systems (ELK, Splunk, etc.)
- Performance: Low overhead when disabled, structured context when enabled
Log Levels
Level Policy
| Level | Usage | Examples |
|---|---|---|
error | System failures, data corruption, unrecoverable errors | Database corruption, OOM, panic recovery |
warn | Recoverable failures, degraded performance, misconfigurations | Failed heartbeat, audit sink errors, fallback modes |
info | Operational events, lifecycle changes, important state transitions | Instance startup, lease acquisition, stats completion |
debug | Detailed diagnostics, performance metrics, internal state | Micro-rescan progress, MVCC recovery details, buffer pool stats |
trace | Very verbose debugging, hot path details | Individual tuple processing, lock acquisition |
Production Recommendations
- Production:
info(default) - captures operational events without performance impact - Troubleshooting:
debug- detailed diagnostics for performance analysis - Development:
trace- full verbosity for debugging
Configuration
Static Configuration (angarabase.conf)
[logging]
log_level = "info"
Supported values: error, warn, info, debug, trace
Default: info
Restart required: No (dynamic setting)
Environment Variable Override
export ANGARABASE_LOG_LEVEL=debug
./angarabase-server --config /etc/angarabase/angarabase.conf
Environment variables take precedence over config file settings during bootstrap.
Runtime Configuration
Change log level without restart using SQL:
-- Check current setting
SELECT * FROM sys.settings WHERE name = 'logging.log_level';
-- Change to debug level
SELECT sys.set_setting('logging.log_level', 'debug');
-- Verify change
SELECT * FROM sys.settings WHERE name = 'logging.log_level';
Note: Runtime changes are volatile and reset on restart. Update angarabase.conf for persistent changes.
Log Format
Structure
All log messages follow this format:
2026-03-09T10:30:45.123Z INFO [angarabase_server::stats] stats_scheduler: auto_analyze_triggered table=users staleness_score=2.45
Components:
- Timestamp: ISO 8601 with millisecond precision
- Level: ERROR/WARN/INFO/DEBUG/TRACE
- Module: Rust module path (e.g.,
angarabase_server::stats) - Context: Structured
key=valuepairs with operation context
Context Format
Log messages use consistent key=value structured context:
#![allow(unused)]
fn main() {
// Good: structured context
log::info!("instance_lease: acquired holder={} expires_at={}", holder_id, expires_at);
// Good: operation context
log::debug!("micro_rescan: completed table={} scanned_rows={} duration={:?}", table, rows, duration);
// Good: error context
log::warn!("audit_sink: write_failed path={} err={}", path, error);
}
Context Guidelines:
- Use
snake_casefor keys - Include operation prefix (e.g.,
micro_rescan:,instance_lease:) - Provide enough context for troubleshooting
- Avoid sensitive data in logs (use IDs, not content)
Production Deployment
Log Aggregation
AngaraBase structured logs integrate well with log aggregation systems:
ELK Stack:
# logstash.conf
filter {
if [program] == "angarabase-server" {
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} \[%{DATA:module}\] %{GREEDYDATA:context}" }
}
kv {
source => "context"
field_split => " "
value_split => "="
}
}
}
Splunk:
[angarabase]
EXTRACT-level = (?<level>ERROR|WARN|INFO|DEBUG|TRACE)
EXTRACT-module = \[(?<module>[^\]]+)\]
EXTRACT-operation = (?<operation>\w+):
Log Rotation
Configure log rotation for production deployments:
# /etc/logrotate.d/angarabase
/var/log/angarabase/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0644 angarabase angarabase
postrotate
systemctl reload angarabase-server
endscript
}
Monitoring
Key log patterns to monitor:
# Error rate monitoring
grep "ERROR" /var/log/angarabase/server.log | wc -l
# Instance lease issues
grep "instance_lease.*failed" /var/log/angarabase/server.log
# Performance degradation
grep "stats_scheduler.*io_backpressure" /var/log/angarabase/server.log
# MVCC recovery events
grep "mvcc_recovery:" /var/log/angarabase/server.log
Troubleshooting
Common Issues
High log volume at debug level:
-- Reduce to info level
SELECT sys.set_setting('logging.log_level', 'info');
Missing log output:
# Check RUST_LOG environment variable
echo $RUST_LOG
# Override with explicit filter
export RUST_LOG=angarabase_server=debug,rustls=warn
Log format parsing issues:
- Ensure timestamp parsing handles millisecond precision
- Context parsing should handle
key=valuepairs with spaces - Module names contain
::separators
Performance Impact
Log level performance characteristics:
| Level | Overhead | Use Case |
|---|---|---|
error/warn | Minimal | Always safe in production |
info | Low | Default production level |
debug | Moderate | Short-term troubleshooting |
trace | High | Development/debugging only |
Recommendation: Use info for production, temporarily increase to debug for troubleshooting specific
issues.
Migration Notes
From println! to log::*!
Current implementation migrated all production println! calls to structured logging:
- 60+ calls across 11 files replaced
- Backward compatibility: No breaking changes to existing functionality
- Enhanced context: More structured information for operations
Future Enhancements (Phase 2)
Planned for next releases:
- Tracing integration: Distributed tracing with spans
- OpenTelemetry: OTLP export for APM systems
- Metrics correlation: Link logs with performance metrics
- Sampling: Adaptive sampling for high-volume environments
See Also
- RFC-2026-360: Structured Logging & Tracing v0
- Instance Lifecycle - Instance lease logging
- Crash Recovery - MVCC recovery logging
- Settings Management - Runtime configuration
AngaraBase Tracing Operations Guide
Audience: Database operators, SREs, performance engineers
Overview
AngaraBase включает structured tracing на базе tracing crate с поддержкой OpenTelemetry. Эта система
заменяет legacy env_logger и обеспечивает end-to-end visibility для query execution pipeline.
Key Benefits:
- End-to-end spans:
accept → authenticate → parse → plan → execute → storage → response - Каждый запрос имеет уникальный
trace_id - JSON-структурированные логи для machine parsing
- Интеграция с Jaeger/Tempo через OpenTelemetry
- Автоматическая propagation tracing context через async/sync boundaries
Configuration
Basic Setup
В angarabase.conf:
[diagnostics]
# Tracing output format: "text" (human-readable) или "json" (structured)
tracing_format = "json"
# Log level filtering (same as RUST_LOG)
log_level = "info"
Environment Variables
| Variable | Description | Example |
|---|---|---|
RUST_LOG | Log level filter | RUST_LOG=angarabase=debug,tokio=info |
ANGARABASE_OTLP_ENDPOINT | OpenTelemetry collector endpoint | http://jaeger:14268/api/traces |
ANGARABASE_TRACE_SAMPLE_RATE | Sampling rate (0.0-1.0) | 0.1 (10% sampling) |
JSON vs Text Format
Text format (human-readable):
2026-03-12T10:30:45.123Z INFO angarabase::query::executor: query_start session_id=12345 sql="SELECT * FROM users"
2026-03-12T10:30:45.125Z DEBUG angarabase::query::planner: plan_created plan_hash=abc123 estimated_rows=1000
JSON format (machine-parseable):
{"timestamp":"2026-03-12T10:30:45.123Z","level":"INFO","target":"angarabase::query::executor","fields":{"session_id":12345,"sql":"SELECT * FROM users"},"span":{"name":"query_execution","trace_id":"abc123"}}
Tracing Architecture
Span Hierarchy
query_execution (root span)
├── parse (SQL → AST)
├── plan (AST → execution plan)
├── execute
│ ├── storage_io (page reads/writes)
│ ├── lock_acquisition
│ └── wal_flush
└── commit (autocommit finalization)
Span Propagation
AngaraBase автоматически propagates tracing context через:
- Async boundaries:
tokio::task::spawn_blockingcalls - Thread pool: Worker thread execution
- Network layer: AngaraNet io_uring/tokio integration
Implementation pattern:
#![allow(unused)]
fn main() {
let span = tracing::Span::current();
tokio::task::spawn_blocking(move || {
let _enter = span.enter();
// Sync code here inherits tracing context
engine.execute(&query)
}).await
}
Operational Procedures
Enabling Tracing
- Development/Debug:
RUST_LOG=angarabase=trace ./angarabase-server
- Production (JSON logs):
# angarabase.conf
[diagnostics]
tracing_format = "json"
log_level = "info"
- OpenTelemetry Export:
export ANGARABASE_OTLP_ENDPOINT=http://jaeger:14268/api/traces
export ANGARABASE_TRACE_SAMPLE_RATE=0.05 # 5% sampling
./angarabase-server
Monitoring Query Performance
1. Slow Query Detection
Text logs:
grep "query_execution.*duration_ms" /var/log/angarabase.log | \
awk '$NF > 1000' | head -10 # Queries > 1 second
JSON logs:
jq 'select(.span.name == "query_execution" and .fields.duration_ms > 1000)' \
/var/log/angarabase.log
2. Per-Phase Timing Analysis
Look for spans with names: parse, plan, execute, commit
Example JSON query:
jq 'select(.span.name == "execute" and .fields.duration_ms > 500)' \
/var/log/angarabase.log | \
jq '.fields | {trace_id, duration_ms, estimated_rows}'
3. Lock Contention Detection
# Find queries waiting on locks
jq 'select(.fields.wait_event_type == "Lock")' /var/log/angarabase.log
Troubleshooting Common Issues
High Parse Time
# Find queries with slow parsing
jq 'select(.span.name == "parse" and .fields.duration_ms > 100)' \
/var/log/angarabase.log | jq '.fields.sql'
Common causes:
- Complex SQL with many JOINs
- Large IN clauses
- Deeply nested subqueries
High Plan Time
# Find queries with slow planning
jq 'select(.span.name == "plan" and .fields.duration_ms > 200)' \
/var/log/angarabase.log
Common causes:
- Missing statistics
- Complex join ordering
- Large number of tables
High Execute Time
# Correlate with storage I/O
jq 'select(.span.name == "storage_io" and .fields.duration_ms > 1000)' \
/var/log/angarabase.log
Common causes:
- Sequential scans
- I/O bottlenecks
- Lock contention
Integration with External Tools
Jaeger Integration
- Setup Jaeger:
docker run -d --name jaeger \
-p 14268:14268 -p 16686:16686 \
jaegertracing/all-in-one:latest
- Configure AngaraBase:
export ANGARABASE_OTLP_ENDPOINT=http://localhost:14268/api/traces
- View traces: http://localhost:16686
Grafana/Tempo Integration
# tempo.yaml
server:
http_listen_port: 3200
distributor:
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
storage:
trace:
backend: local
local:
path: /tmp/tempo/traces
Log Aggregation (ELK Stack)
Logstash configuration:
input {
file {
path => "/var/log/angarabase.log"
codec => "json"
}
}
filter {
if [span][name] {
mutate {
add_field => { "trace_operation" => "%{[span][name]}" }
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "angarabase-traces-%{+YYYY.MM.dd}"
}
}
Performance Impact
Overhead Measurements
| Configuration | CPU Overhead | Latency Impact |
|---|---|---|
| Text format, INFO level | < 1% | < 5ms p99 |
| JSON format, INFO level | < 2% | < 8ms p99 |
| JSON + OTLP export, 5% sampling | < 3% | < 10ms p99 |
| JSON + OTLP export, 100% sampling | < 8% | < 20ms p99 |
Production Recommendations
- Use JSON format for structured log processing
- Set appropriate log levels:
INFOfor production,DEBUGfor troubleshooting - Configure OTLP sampling: 1-10% for high-traffic systems
- Monitor log volume: JSON logs are ~2x larger than text
Alerting and Monitoring
Key Metrics to Monitor
- Query Duration Distribution:
histogram_quantile(0.95,
rate(angarabase_query_duration_seconds_bucket[5m])
)
- Slow Query Count:
increase(angarabase_slow_queries_total[5m])
- Tracing Overhead:
rate(angarabase_tracing_events_total[5m])
Alerting Rules
groups:
- name: angarabase_tracing
rules:
- alert: HighQueryLatency
expr: |
histogram_quantile(0.95,
rate(angarabase_query_duration_seconds_bucket[5m])
) > 1.0
for: 2m
labels:
severity: warning
annotations:
summary: "AngaraBase query latency is high"
- alert: TracingVolumeHigh
expr: |
rate(angarabase_tracing_events_total[5m]) > 1000
for: 5m
labels:
severity: info
annotations:
summary: "AngaraBase tracing volume is high"
Security Considerations
Sensitive Data in Logs
⚠️ WARNING: Tracing logs may contain SQL queries with sensitive data.
Mitigation strategies:
- Query parameter redaction:
[diagnostics]
redact_query_params = true # Replace literals with ?
- Log rotation and retention:
# logrotate configuration
/var/log/angarabase.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
}
- Access control:
chmod 640 /var/log/angarabase.log
chown angarabase:angarabase-ops /var/log/angarabase.log
OTLP Export Security
# Use TLS for OTLP export
export ANGARABASE_OTLP_ENDPOINT=https://jaeger.internal:14268/api/traces
export ANGARABASE_OTLP_TLS_CERT=/etc/ssl/certs/angarabase.crt
export ANGARABASE_OTLP_TLS_KEY=/etc/ssl/private/angarabase.key
Troubleshooting
Common Issues
1. No Tracing Output
Symptoms: No tracing spans in logs Causes:
RUST_LOGnot set or too restrictivetracing_formatmisconfigured- Tracing not enabled in binary
Solution:
# Check tracing is compiled in
./angarabase-server --version | grep tracing
# Enable debug tracing
RUST_LOG=angarabase=debug ./angarabase-server
2. Missing Span Context
Symptoms: Broken trace chains, missing parent-child relationships Causes:
- Missing
span.enter()inspawn_blockingcalls - Incorrect async context propagation
Solution: Check for proper span propagation pattern in code
3. High Log Volume
Symptoms: Disk space issues, performance degradation Causes:
- Log level too verbose (
TRACEin production) - No log rotation
- High query volume
Solution:
# Reduce log level
export RUST_LOG=angarabase=info
# Enable log rotation
logrotate -f /etc/logrotate.d/angarabase
4. OTLP Export Failures
Symptoms: Traces not appearing in Jaeger/Tempo Causes:
- Network connectivity issues
- Incorrect endpoint configuration
- Authentication failures
Solution:
# Test OTLP endpoint
curl -v $ANGARABASE_OTLP_ENDPOINT/health
# Check AngaraBase logs for export errors
grep "otlp.*error" /var/log/angarabase.log
Advanced Topics
Custom Span Attributes
AngaraBase automatically adds these attributes to spans:
| Attribute | Description | Example |
|---|---|---|
session_id | Database session ID | 12345 |
query_fingerprint | SQL query hash | abc123def |
plan_hash | Execution plan hash | def456ghi |
estimated_rows | Query planner estimate | 1000 |
actual_rows | Actual rows returned | 987 |
wait_event_type | Current wait type | Lock, IO, Net |
wait_event | Specific wait event | RowLock, PageRead |
Correlation with System Metrics
CPU correlation:
# Find high-CPU queries
jq 'select(.span.name == "execute" and .fields.cpu_time_ms > 1000)' \
/var/log/angarabase.log
I/O correlation:
# Find I/O-heavy queries
jq 'select(.fields.io_reads > 1000 or .fields.io_writes > 100)' \
/var/log/angarabase.log
Custom Dashboards
Grafana query examples:
- Query throughput by operation:
sum(rate(angarabase_queries_total[5m])) by (operation)
- Average query duration by phase:
avg(angarabase_query_phase_duration_seconds) by (phase)
- Lock contention rate:
sum(rate(angarabase_wait_events_total{type="Lock"}[5m]))
References
- RFC-2026-360: Structured Logging and Tracing v0
- RFC-2026-461: Async Runtime Migration Strategy v0
- CODING_STANDARDS.md: Tracing guidelines (§9)
- ASYNC_GUIDELINES.md: Span propagation patterns
- Tracing crate docs: https://docs.rs/tracing/
- OpenTelemetry spec: https://opentelemetry.io/docs/
Contact: Database SRE team Last updated: 2026-03-12 by current implementation phase
AngaraBase USDT Probes Operations Guide
Audience: Database operators, performance engineers, eBPF developers
Overview
AngaraBase включает User Statically-Defined Tracing (USDT) probes — zero-overhead instrumentation points для интеграции с eBPF-инструментами (bpftrace, bcc, pg_expecto).
Key Benefits:
- Zero overhead when not attached (NOP instructions)
- Real-time attachment без рестарта процесса
- Корреляция engine-level событий с OS-level метриками
- Совместимость с существующими eBPF toolchains
Probe Taxonomy: 12 probe points покрывают query lifecycle и wait events.
Probe Architecture
Probe Categories
| Category | Probes | Description |
|---|---|---|
| Query Lifecycle | query_start, query_end | Full query execution timing |
| Query Phases | phase_start, phase_end | Per-phase timing (parse/plan/exec/commit) |
| Lock Events | lock_wait_start, lock_wait_end | Lock contention measurement |
| I/O Events | io_start, io_end | Storage I/O operations |
| Network Events | net_stall_start, net_stall_end | Network I/O stalls |
| Scheduler Events | sched_wait_start, sched_wait_end | Thread pool queue waits |
Probe Signature
All probes follow consistent ABI:
// Start probes (2 arguments)
probe angarabase:query_start(uint64_t session_id, uint64_t query_fingerprint);
probe angarabase:lock_wait_start(uint64_t session_id, uint8_t lock_type);
// End probes (3-4 arguments)
probe angarabase:query_end(uint64_t session_id, uint64_t query_fingerprint,
uint64_t duration_us, uint8_t outcome);
probe angarabase:lock_wait_end(uint64_t session_id, uint64_t wait_duration_us);
Probe Locations
Probes fire at same instrumentation points as WaitEventGuard RAII:
#![allow(unused)]
fn main() {
// Example: Lock wait instrumentation
let _guard = WaitEventGuard::enter(session_id, WaitEventType::Lock, WaitEvent::RowLock);
// probe_lock_wait_start! fires here
// Blocking operation (lock acquisition)
let result = lock_manager.acquire_lock(&key);
// probe_lock_wait_end! fires when _guard drops
}
Compilation and Feature Flags
Build Configuration
Default build (probes enabled):
cargo build --release
# USDT probes compiled in (zero overhead when not attached)
Minimal build (probes excluded):
cargo build --release --no-default-features
# No USDT probes, smaller binary
Verify probe compilation:
# Check probes are embedded
readelf -n ./target/release/angarabase-server | grep -A5 "stapsdt"
# List available probes
bpftrace -l 'usdt:./target/release/angarabase-server:angarabase:*'
Expected output:
usdt:./target/release/angarabase-server:angarabase:query_start
usdt:./target/release/angarabase-server:angarabase:query_end
usdt:./target/release/angarabase-server:angarabase:phase_start
usdt:./target/release/angarabase-server:angarabase:phase_end
usdt:./target/release/angarabase-server:angarabase:lock_wait_start
usdt:./target/release/angarabase-server:angarabase:lock_wait_end
usdt:./target/release/angarabase-server:angarabase:io_start
usdt:./target/release/angarabase-server:angarabase:io_end
usdt:./target/release/angarabase-server:angarabase:net_stall_start
usdt:./target/release/angarabase-server:angarabase:net_stall_end
usdt:./target/release/angarabase-server:angarabase:sched_wait_start
usdt:./target/release/angarabase-server:angarabase:sched_wait_end
bpftrace Examples
Query Tags
query_tag is a u64 hash (xxh64) propagated through all probe fires for a query/session.
You can set it per-session:
SET query_tag = 'demo-heavy-report';
or per-query:
/*+ angarabase:tag=demo-heavy-report */ SELECT * FROM orders;
The scripts below filter on “tag != 0” (tagged traffic only), so regular traffic keeps zero-overhead behavior.
# 1) Lock + IO latency by tagged query
bpftrace -e '
usdt:./angarabased:angarabase:lock_wait_end /arg2 != 0/ {
@lock_wait_us_by_tag[arg2] = hist(arg1);
}
usdt:./angarabased:angarabase:io_end /arg2 != 0/ {
@io_wait_us_by_tag[arg2] = hist(arg1);
}
'
# 2) Per-operator breakdown (fires only for tag != 0)
bpftrace -e '
usdt:./angarabased:angarabase:operator_end /arg1 != 0/ {
@op_duration_us[arg1, arg2] = hist(arg4);
@op_rows_out[arg1, arg2] = sum(arg3);
}
'
# 3) Compare p99 across tagged query cohorts (A/B)
bpftrace -e '
usdt:./angarabased:angarabase:query_end /arg4 != 0/ {
@query_total_us_by_tag[arg4] = hist(arg2);
@query_rows_by_tag[arg4] = sum(arg5);
}
'
Basic Query Monitoring
1. Query Throughput and Latency
#!/usr/bin/env bpftrace
# query_latency.bt - Monitor query execution time
usdt:./angarabase-server:angarabase:query_start {
@start[arg0] = nsecs; // session_id -> start_time
@queries++;
}
usdt:./angarabase-server:angarabase:query_end {
$duration_us = arg2; // duration from probe
$outcome = arg3; // 0=Ok, 1=Error
delete(@start[arg0]);
if ($outcome == 0) {
@latency_us = hist($duration_us);
@successful++;
} else {
@failed++;
}
}
interval:s:5 {
printf("\n=== Query Stats (5s) ===\n");
printf("Total queries: %d\n", @queries);
printf("Successful: %d\n", @successful);
printf("Failed: %d\n", @failed);
print(@latency_us);
clear(@queries); clear(@successful); clear(@failed);
}
END {
clear(@start); clear(@latency_us);
}
2. Per-Phase Timing Breakdown
#!/usr/bin/env bpftrace
# phase_timing.bt - Analyze query phase performance
usdt:./angarabase-server:angarabase:phase_start {
$session_id = arg0;
$phase = arg1; // 1=parse, 2=plan, 3=execute, 4=commit
@phase_start[$session_id, $phase] = nsecs;
}
usdt:./angarabase-server:angarabase:phase_end {
$session_id = arg0;
$phase = arg1;
$duration_us = arg2;
delete(@phase_start[$session_id, $phase]);
if ($phase == 1) {
@parse_time = hist($duration_us);
} else if ($phase == 2) {
@plan_time = hist($duration_us);
} else if ($phase == 3) {
@exec_time = hist($duration_us);
} else if ($phase == 4) {
@commit_time = hist($duration_us);
}
}
interval:s:10 {
printf("\n=== Phase Timing Distribution ===\n");
printf("Parse time (us):\n"); print(@parse_time);
printf("Plan time (us):\n"); print(@plan_time);
printf("Execute time (us):\n"); print(@exec_time);
printf("Commit time (us):\n"); print(@commit_time);
}
END {
clear(@phase_start);
clear(@parse_time); clear(@plan_time);
clear(@exec_time); clear(@commit_time);
}
Lock Contention Analysis
3. Lock Wait Time Distribution
#!/usr/bin/env bpftrace
# lock_contention.bt - Monitor lock contention
usdt:./angarabase-server:angarabase:lock_wait_start {
$session_id = arg0;
$lock_type = arg1; // Lock type enum
@lock_start[$session_id] = nsecs;
@lock_requests[$lock_type]++;
}
usdt:./angarabase-server:angarabase:lock_wait_end {
$session_id = arg0;
$wait_duration_us = arg1;
delete(@lock_start[$session_id]);
@lock_wait_time = hist($wait_duration_us);
if ($wait_duration_us > 1000) { // > 1ms
@slow_locks++;
printf("SLOW LOCK: session=%d wait=%d us\n", $session_id, $wait_duration_us);
}
}
interval:s:5 {
printf("\n=== Lock Contention Stats ===\n");
printf("Lock requests by type:\n"); print(@lock_requests);
printf("Lock wait time distribution (us):\n"); print(@lock_wait_time);
printf("Slow locks (>1ms): %d\n", @slow_locks);
clear(@lock_requests); clear(@slow_locks);
}
END {
clear(@lock_start); clear(@lock_wait_time);
}
I/O Performance Monitoring
4. Storage I/O Latency
#!/usr/bin/env bpftrace
# io_latency.bt - Monitor storage I/O performance
usdt:./angarabase-server:angarabase:io_start {
$session_id = arg0;
$op_type = arg1; // I/O operation type
$bytes = arg2; // Bytes to read/write
@io_start[$session_id] = nsecs;
@io_bytes += $bytes;
@io_ops++;
}
usdt:./angarabase-server:angarabase:io_end {
$session_id = arg0;
$latency_us = arg1;
delete(@io_start[$session_id]);
@io_latency = hist($latency_us);
if ($latency_us > 10000) { // > 10ms
@slow_io++;
printf("SLOW I/O: session=%d latency=%d us\n", $session_id, $latency_us);
}
}
interval:s:5 {
printf("\n=== I/O Performance Stats ===\n");
printf("Total I/O ops: %d\n", @io_ops);
printf("Total I/O bytes: %d\n", @io_bytes);
printf("I/O latency distribution (us):\n"); print(@io_latency);
printf("Slow I/O ops (>10ms): %d\n", @slow_io);
clear(@io_ops); clear(@io_bytes); clear(@slow_io);
}
END {
clear(@io_start); clear(@io_latency);
}
Advanced Use Cases
Correlation with System Events
5. Engine + Kernel Correlation
#!/usr/bin/env bpftrace
# engine_kernel_correlation.bt - Correlate AngaraBase events with kernel
#include <linux/sched.h>
// Track AngaraBase query starts
usdt:./angarabase-server:angarabase:query_start {
@query_pids[pid] = 1;
@query_start_time[arg0] = nsecs; // session_id -> start_time
}
// Track context switches for AngaraBase processes
tracepoint:sched:sched_switch {
$prev_pid = args->prev_pid;
$next_pid = args->next_pid;
// Track when AngaraBase process gets scheduled out
if (@query_pids[$prev_pid]) {
@context_switches[$prev_pid]++;
}
}
// Track page faults for AngaraBase processes
tracepoint:exceptions:page_fault_user {
if (@query_pids[pid]) {
@page_faults[pid]++;
}
}
usdt:./angarabase-server:angarabase:query_end {
$session_id = arg0;
$duration_us = arg2;
delete(@query_start_time[$session_id]);
printf("Query session=%d duration=%d us ctx_switches=%d page_faults=%d\n",
$session_id, $duration_us, @context_switches[pid], @page_faults[pid]);
}
END {
clear(@query_pids); clear(@query_start_time);
clear(@context_switches); clear(@page_faults);
}
Custom Aggregations
6. Top Slow Queries by Fingerprint
#!/usr/bin/env bpftrace
# top_slow_queries.bt - Track slowest queries by fingerprint
usdt:./angarabase-server:angarabase:query_end {
$session_id = arg0;
$query_fingerprint = arg1;
$duration_us = arg2;
$outcome = arg3;
if ($outcome == 0 && $duration_us > 1000) { // Successful queries > 1ms
@slow_queries[$query_fingerprint] = hist($duration_us);
@query_count[$query_fingerprint]++;
@total_time[$query_fingerprint] += $duration_us;
}
}
interval:s:30 {
printf("\n=== Top 10 Slowest Query Fingerprints ===\n");
print(@slow_queries, 10);
printf("\n=== Query Execution Counts ===\n");
print(@query_count, 10);
printf("\n=== Total Time by Fingerprint (us) ===\n");
print(@total_time, 10);
}
END {
clear(@slow_queries); clear(@query_count); clear(@total_time);
}
Production Deployment
Performance Impact
| Configuration | CPU Overhead | Memory Overhead |
|---|---|---|
| Probes compiled, not attached | 0% | +~50KB binary size |
| Light monitoring (query_start/end) | < 0.5% | +~1MB |
| Full monitoring (all 12 probes) | < 2% | +~5MB |
| Heavy aggregation (histograms) | < 5% | +~20MB |
Recommended Monitoring Strategy
Production Environment
# Light monitoring - query throughput and basic latency
bpftrace query_latency.bt
# Periodic deep-dive - run for 5 minutes every hour
*/60 * * * * timeout 300 bpftrace phase_timing.bt > /var/log/angarabase-phase-timing.log
Troubleshooting Environment
# Full monitoring during incident investigation
bpftrace lock_contention.bt &
bpftrace io_latency.bt &
bpftrace engine_kernel_correlation.bt &
# Stop all monitoring
pkill bpftrace
Security Considerations
Required Capabilities
# BPF capability required for probe attachment
sudo setcap cap_bpf+ep /usr/bin/bpftrace
# Alternative: run as root (not recommended)
sudo bpftrace query_latency.bt
Access Control
# Restrict bpftrace access to specific group
groupadd angarabase-monitoring
usermod -a -G angarabase-monitoring monitoring-user
# Set appropriate permissions
chown root:angarabase-monitoring /usr/bin/bpftrace
chmod 750 /usr/bin/bpftrace
Integration with Monitoring Systems
Prometheus Integration
#!/bin/bash
# angarabase_probe_exporter.sh - Export probe metrics to Prometheus
# Run bpftrace and parse output
bpftrace -e '
usdt:./angarabase-server:angarabase:query_end {
@query_duration_sum += arg2;
@query_count++;
}
interval:s:15 {
printf("angarabase_query_duration_sum %d\n", @query_duration_sum);
printf("angarabase_query_count %d\n", @query_count);
clear(@query_duration_sum); clear(@query_count);
}
' | while read line; do
echo "$line" > /var/lib/prometheus/node-exporter/angarabase-probes.prom.$$
mv /var/lib/prometheus/node-exporter/angarabase-probes.prom.$$ \
/var/lib/prometheus/node-exporter/angarabase-probes.prom
done
Grafana Dashboard
{
"dashboard": {
"title": "AngaraBase USDT Probes",
"panels": [
{
"title": "Query Rate",
"type": "stat",
"targets": [
{
"expr": "rate(angarabase_query_count[5m])",
"legendFormat": "Queries/sec"
}
]
},
{
"title": "Average Query Latency",
"type": "stat",
"targets": [
{
"expr": "rate(angarabase_query_duration_sum[5m]) / rate(angarabase_query_count[5m])",
"legendFormat": "Avg latency (us)"
}
]
}
]
}
}
Troubleshooting
Common Issues
1. No Probes Listed
Symptoms:
$ bpftrace -l 'usdt:./angarabase-server:angarabase:*'
# No output
Causes:
- Binary compiled with
--no-default-features - Wrong binary path
- Probes stripped during build
Solution:
# Verify binary has probes
readelf -n ./angarabase-server | grep stapsdt
# Check build configuration
./angarabase-server --version | grep usdt
# Rebuild with probes
cargo build --release --features usdt
2. Permission Denied
Symptoms:
$ bpftrace query_latency.bt
ERROR: failed to attach probe
Causes:
- Missing BPF capabilities
- SELinux/AppArmor restrictions
- Kernel version incompatibility
Solution:
# Add BPF capability
sudo setcap cap_bpf+ep /usr/bin/bpftrace
# Check kernel version (requires 4.9+)
uname -r
# Temporary workaround
sudo bpftrace query_latency.bt
3. High Overhead
Symptoms:
- CPU usage increase > 5%
- Query latency degradation
- Memory usage growth
Causes:
- Too many active probes
- Heavy aggregation (histograms)
- High-frequency events
Solution:
# Reduce monitoring frequency
interval:s:60 { ... } # Instead of interval:s:5
# Use sampling
usdt:./angarabase-server:angarabase:query_start / pid % 10 == 0 / {
# Monitor only 10% of queries
}
# Limit histogram buckets
@latency = hist($duration_us, 0, 10000, 100); # 100 buckets max
4. Missing Events
Symptoms:
- Expected probes don’t fire
- Incomplete event sequences
- Zero counts in monitoring
Causes:
- Process not using instrumented code paths
- Probe attachment race condition
- Incorrect probe signatures
Solution:
# Verify process is running instrumented code
ps aux | grep angarabase-server
# Check probe attachment
bpftrace -l 'usdt:*:angarabase:*' | grep $(pgrep angarabase-server)
# Debug probe firing
bpftrace -e 'usdt:./angarabase-server:angarabase:* { printf("probe=%s\n", probe); }'
Best Practices
Probe Development
- Start Simple: Begin with basic query_start/query_end monitoring
- Add Gradually: Introduce additional probes based on specific needs
- Test Impact: Measure overhead before deploying to production
- Use Sampling: For high-traffic systems, sample events (e.g., 1 in 100)
Script Organization
# Directory structure
/opt/angarabase/monitoring/
├── scripts/
│ ├── query_latency.bt
│ ├── lock_contention.bt
│ └── io_performance.bt
├── dashboards/
│ └── grafana-angarabase-probes.json
└── exporters/
└── prometheus-exporter.sh
Monitoring Strategy
- Always-On: Basic query throughput and latency
- Periodic: Detailed phase timing (every hour for 5 minutes)
- On-Demand: Lock contention and I/O analysis during incidents
- Correlation: Engine + kernel events for deep troubleshooting
References
- RFC-2026-369: USDT eBPF Observability Probes v0
- bpftrace documentation: https://github.com/iovisor/bpftrace
- BCC tools: https://github.com/iovisor/bcc
- USDT specification: https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation
- Linux eBPF: https://ebpf.io/
Contact: Database SRE team Last updated: 2026-03-12 by current implementation phase
GC auto-tuning
Status: Production-ready Contract: RFC-2026-034 §12 (AngaraGC Phase 4 auto-tuning)
Overview
AngaraGC auto-tuning automatically adjusts Garbage Collection budgets based on workload telemetry:
- Bloat ratio — how much dead data accumulates
- Epoch lag — how far behind active transactions are from committed state
- Cycle latency — how long each GC cycle takes
The controller uses a PID-like feedback loop to balance aggressive cleanup (high budget) against latency impact (low budget).
Configuration
Enable auto-tuning
export ANGARABASE_GC_BACKGROUND=1 # Enable GC background worker
export ANGARABASE_GC_AUTO_TUNING=1 # Enable auto-tuning controller
Or via config file:
[gc]
auto_tuning_enabled = true
Tuning parameters (optional)
Default values are production-safe. Override only if you understand the trade-offs:
# Target bloat ratio (default: 20%)
export ANGARABASE_GC_TARGET_BLOAT_RATIO=20
# Target epoch lag (default: 1000 epochs)
export ANGARABASE_GC_TARGET_LAG=1000
# Latency spike threshold (default: 100ms)
export ANGARABASE_GC_LATENCY_THRESHOLD=100
# Budget bounds (default: 100..100000 tuples/cycle)
export ANGARABASE_GC_BUDGET_MIN=100
export ANGARABASE_GC_BUDGET_MAX=100000
Monitoring
View current auto-tuning state
SELECT * FROM sys.gc_tuning_status;
Returns:
current_budget— current GC budget (tuples/cycle)current_sleep_ms— current sleep interval between cyclestuning_decision— last decision (increase,decrease,hold)
Prometheus metrics
# Controller state
angarabase_gc_tuning_budget_tuples_per_cycle
angarabase_gc_tuning_sleep_ms
angarabase_gc_tuning_bloat_ratio_percent
angarabase_gc_tuning_min_active_epoch_lag
angarabase_gc_tuning_cycle_duration_ms_last
# Decision counters
angarabase_gc_tuning_decision_total_increase
angarabase_gc_tuning_decision_total_decrease
angarabase_gc_tuning_decision_total_hold
Operational notes
When to enable
- Production workloads with variable load: auto-tuning adapts to workload changes
- High bloat risk: auto-tuning increases budget when bloat accumulates
- Latency-sensitive workloads: auto-tuning backs off when GC causes latency spikes
When NOT to enable
- Predictable workloads with stable budget: manual tuning may be simpler
- Debugging GC issues: disable auto-tuning to isolate issues with fixed budget
Bounds safety
- Controller never violates
min_budgetormax_budget - Bounds clamp adaptive adjustments, ensuring predictable worst-case behavior
- Default bounds are conservative; adjust only after profiling
Troubleshooting
Auto-tuning oscillates
Symptom: Decision alternates increase/decrease rapidly.
Fix: Increase latency threshold or bloat target to reduce sensitivity:
export ANGARABASE_GC_LATENCY_THRESHOLD=200 # more tolerance for latency
export ANGARABASE_GC_TARGET_BLOAT_RATIO=30 # more tolerance for bloat
Budget stuck at min/max
Symptom: current_budget reaches bound and stays there.
Diagnosis:
- Stuck at max: Bloat or lag persistently above target → increase
max_budgetor investigate workload - Stuck at min: Latency spikes persist → investigate GC contention or reduce GC work
Reference
- RFC-2026-034 §12: AngaraGC auto-tuning design
- Implementation scope
crates/angarabased/src/gc_worker.rs: Controller implementationcrates/angarabase/src/virtual_catalog/mod.rs:sys.gc_tuning_statusview
Дальше
После того как angara_gc.auto_tuning = on и метрики GC стабилизировались:
- Диагностика — как читать
sys.healthи метрики GC под нагрузкой. - Мониторинг — какие алерты завести на зону «GC backlog растёт».
- Транзакции и MVCC — концептуально, что именно AngaraGC чистит.
Инцидентный runbook: debug ошибок за 10 минут
Goal
Быстро локализовать причину деградации/ошибок в production: понять что ломается (logs/tracing) и где узкое место (USDT wait events + eBPF).
Prerequisites
- Запущен
angarabase-server. - Доступ к серверным логам.
- Доступ к SQL-клиенту (
psql/pgwire). - Для USDT/eBPF: Linux с поддержкой eBPF, установлен
bpftrace, есть права (CAP_BPF/CAP_PERFMONили root).
Быстрый сценарий (10 минут)
Шаг 1 (0-2 мин): зафиксировать симптом и affected sessions
Проверить активные сессии и wait state:
SELECT pid, state, wait_event_type, wait_event, query
FROM angara_stat_activity
ORDER BY pid;
Если проблема массовая — сохранить снимок в инцидентный тикет/чат.
Шаг 2 (2-4 мин): понять, что именно падает или деградирует
По логам найти ERROR/WARN по времени инцидента:
rg "ERROR|WARN|panic|timeout|failed|degraded" /var/log/angarabase.log
Если включён tracing (JSON), быстро отфильтровать длинные операции:
jq 'select(.fields.duration_ms != null and .fields.duration_ms > 1000)' /var/log/angarabase.log
Интерпретация:
- много
Lock/timeout-> вероятен contention; - много
io/fsync/wal-> вероятен storage bottleneck; - сетевые ошибки -> вероятен
Netpath.
Шаг 3 (4-7 мин): снять runtime evidence через USDT probes
Проверить, что probes доступны:
bpftrace -l 'usdt:./angarabase-server:angarabase:*'
Быстрая гистограмма lock waits:
bpftrace -e 'usdt:./angarabase-server:angarabase:lock_wait_end { @lock_us = hist(arg1); } interval:s:10 { print(@lock_us); clear(@lock_us); }'
Быстрая гистограмма I/O latency:
bpftrace -e 'usdt:./angarabase-server:angarabase:io_end { @io_us = hist(arg1); } interval:s:10 { print(@io_us); clear(@io_us); }'
Быстрый срез query latency:
bpftrace -e 'usdt:./angarabase-server:angarabase:query_end { @q_us = hist(arg2); } interval:s:10 { print(@q_us); clear(@q_us); }'
Шаг 4 (7-9 мин): корреляция и гипотеза root cause
Сопоставить:
angara_stat_activity.wait_event_type- логи/трейсы
- USDT-гистограммы
Правило triage:
- высокий
lock_wait_end+wait_event_type=Lock-> contention/serialization; - высокий
io_end+ storage warnings -> disk/flush path; - нормальный lock/io, но высокий
query_end-> planner/execute CPU path.
Шаг 5 (9-10 мин): зафиксировать evidence и next action
Минимум в отчёт:
- окно времени;
- top symptoms из логов;
- 1-2 команды и их вывод (гистограммы);
- предварительный root cause;
- immediate mitigation (например, снизить нагрузку, ограничить тяжелые запросы, усилить мониторинг).
Expected result
За 10 минут есть:
- воспроизводимый evidence-пакет;
- первичная классификация инцидента (Lock/IO/Net/CPU/Scheduler);
- понятный следующий шаг для mitigation/fix.
Troubleshooting
| Symptom | Action |
|---|---|
bpftrace не видит probes | Проверить бинарь и секцию stapsdt: `readelf -n ./angarabase-server |
failed to attach probe | Запустить с правами root или выдать capability для bpftrace |
| Логи есть, но root cause не ясен | Усилить уровень логирования на время инцидента + повторить USDT-срез на 60-120 секунд |
phase_* probes плохо коррелируются между сессиями | Использовать query_*, lock_*, io_* как primary signal; phase_* считать вспомогательными |
Links
- Structured logging: Структурированное логирование
- Tracing: Tracing
- USDT probes: USDT probes
- Общая диагностика: Диагностика
GOST crypto profiles setup
Status: Production-ready, opt-in Contract: Provider-based GOST support (OQ-2026-022 Option A)
Overview
AngaraBase supports GOST cipher suites for TLS 1.2 in regulated environments (ГОСТ 28147-89, ГОСТ Р 34.10-2012).
Key properties:
- Opt-in: GOST disabled by default
- Fail-closed: Server refuses to start if GOST is enabled but crypto provider is incompatible
- Provider-based: Uses OpenSSL GOST engine or compatible crypto provider (not bundled)
Prerequisites
1. Install GOST crypto provider
Option A: OpenSSL with GOST engine (Linux)
# Install OpenSSL with GOST support
sudo apt-get install openssl libssl-dev libengines-gost
# Verify GOST engine is available
openssl engine gost -c
Option B: Custom provider
Implement GostCryptoProvider trait in crates/angarabase/src/security/crypto.rs.
2. Generate TLS certificates
# Generate server certificate with GOST algorithm
openssl req -new -x509 -days 365 \
-newkey gost2012_256 \
-keyout server.key \
-out server.crt \
-nodes \
-subj "/CN=localhost"
Configuration
Enable GOST cipher suites
export ANGARABASE_TLS_ENABLE=1
export ANGARABASE_TLS_CERT_PATH=/path/to/server.crt
export ANGARABASE_TLS_KEY_PATH=/path/to/server.key
export ANGARABASE_TLS_GOST_ENABLED=1
export ANGARABASE_TLS_GOST_CIPHER_SUITES="GOST2012-GOST8912-GOST8912"
Or via config file:
[tls]
enable = true
cert_path = "/etc/angarabase/tls/server.crt"
key_path = "/etc/angarabase/tls/server.key"
gost_enabled = true
gost_cipher_suites = "GOST2012-GOST8912-GOST8912"
Verify configuration
Check effective settings:
SELECT name, value FROM sys.settings WHERE name LIKE 'tls.%';
Expected output:
tls.enable | true
tls.cert_path | /etc/angarabase/tls/server.crt
tls.key_path | /etc/angarabase/tls/server.key
tls.gost_enabled | true
tls.gost_cipher_suites | GOST2012-GOST8912-GOST8912
Client connection
psql with GOST
Requires psql built with OpenSSL GOST support:
psql "host=localhost port=5152 dbname=mydb sslmode=require"
Verify cipher suite
From client:
SHOW ssl_cipher;
Should return GOST cipher suite name.
Security notes
Fail-closed behavior
- If
ANGARABASE_TLS_GOST_ENABLED=1but GOST provider is unavailable, server refuses to start (no silent fallback to standard ciphers) - Invalid cipher suites are rejected at startup (fail-closed validation)
Secrets handling
All tls.* knobs are marked security-sensitive in settings registry:
tls.gost_cipher_suitesis sensitive (policy: alltls.*knobs are security-sensitive per SECURITY_GOVERNANCE.md)- Private key (
tls.key_path) is never exposed insys.settingsor logs
Troubleshooting
Server fails to start with “GOST provider not available”
Cause: GOST crypto provider is not installed or OpenSSL GOST engine is missing.
Fix: Install OpenSSL GOST support (see Prerequisites).
Invalid cipher suites error
Cause: tls.gost_cipher_suites contains invalid cipher names.
Fix: Use valid GOST cipher suite names from OpenSSL GOST engine documentation:
# List available GOST ciphers
openssl ciphers -v | grep GOST
Client connection fails with “no shared cipher”
Cause: Client does not support GOST cipher suites.
Fix: Use psql/libpq built with OpenSSL GOST support.
Limitations (v0)
- Provider availability: GOST support requires compatible crypto provider (not bundled with AngaraBase)
- Platform support: Linux only (OpenSSL GOST engine availability)
- Cipher suite coverage: TLS 1.2 + GOST only (TLS 1.3 GOST deferred to future release)
Reference
- OQ-2026-022: GOST crypto support decision
- Implementation scope
crates/angarabase/src/security/crypto.rs: GOST provider abstraction
Дальше
После того как GOST-провайдер установлен и angarabase стартует с crypto.profile = gost:
- GOST-совместимость — какие сценарии (TLS, TDE, audit-sink) уже покрыты, а какие — roadmap.
- Шифрование (TDE + клиентское) — общий контракт шифрования, в который встроен GOST-профиль.
- Hardening runbook — финальная проверка перед выводом инстанса в production.
Проверка релизных артефактов
Цель
Подтвердить три свойства перед установкой:
- артефакт подлинный (GPG signature);
- артефакт не поврежден (SHA256);
- артефакт соответствует ожидаемой версии.
Пошаговый verify path
VERSION="0.6.3"
ART="angarabase-server-v${VERSION}-x86_64-unknown-linux-gnu.tar.gz"
BASE_URL="https://s3.angarabase.io/stable/v${VERSION}"
# 1) Скачать
curl -fsSL "${BASE_URL}/${ART}" -o "${ART}"
curl -fsSL "${BASE_URL}/${ART}.asc" -o "${ART}.asc"
curl -fsSL "${BASE_URL}/SHA256SUMS" -o SHA256SUMS
# 2) Импортировать release key (один раз)
gpg --keyserver hkps://keys.openpgp.org --recv-keys <KEY_FINGERPRINT>
# альтернатива:
# curl -fsSL https://angarabase.io/release-key.gpg | gpg --import
# 3) Проверить подпись
gpg --verify "${ART}.asc" "${ART}"
# 4) Проверить checksum
sha256sum --check --ignore-missing SHA256SUMS
Критерии успеха
gpg --verifyвозвращаетGood signature.sha256sum --checkвозвращаетOK.
Если любой шаг не проходит — артефакт использовать нельзя.
Дальше
После того как подпись и SHA-256 совпали:
- Установка — распаковать проверенный архив или поставить пакет.
- GOST crypto setup — если требуется отечественная криптография на этапе верификации.
- Поддержка и сбор артефактов баг-репорта — что делать, если хеш не совпал.
Operations Overview
Канонический operations-корпус AngaraBase для DBA и SRE. Здесь собраны runbooks, baselines и контрольные списки, поддерживаемые в синхронизации с кодом и release trains.
Если вы только начинаете — начните с пользовательских руководств в Эксплуатация (How-to): они короче и подходят как entry point. Этот раздел — operator-level deep-dives.
Как ориентироваться
| Задача | Куда идти |
|---|---|
| Поднять инстанс с нуля | Установка → Configuration |
| Запустить контейнер / k8s minimal | Container deployment quickstart |
| Перевести в production | Operational policies baseline → Hardening → Security operations baseline |
| Настроить мониторинг и алерты | Observability metrics checklist → Parallel runtime observability |
| Расследовать проблему в production | Troubleshooting guide → Diagnostics bundle runbook → Error debug runbook |
| Читать планы запросов | How to read query plans → Performance tuning guide |
| Оптимизировать производительность | Performance tuning guide → How to read query plans → Parallel runtime observability |
| Резервная копия / восстановление | Backup and restore (operator-level) → Disaster recovery playbook |
| Обновить версию | Upgrade and migration |
| Подключить незнакомый клиент / ORM | Client compatibility baseline |
| Подготовить voucher для bug-репорта | Diagnostics bundle runbook → Support |
Каноничные operations-страницы
Lifecycle
- Upgrade and migration — pre-flight, rolling steps, verification.
- MVCC and GC operator minimum — поведение AngaraGC и операторские knobs.
- Checkpoint operations — управление процессом checkpoint.
Reliability
- Container deployment quickstart — image-first запуск, cgroup probe, k8s minimal smoke.
- Backup and restore — operator-level baseline (cold + online/PITR).
- Disaster recovery playbook — DR-сценарии, host migration.
- Replication v2 operations guide — AngaraReplica v2.
Performance
- Performance tuning guide — workload-driven knobs, what to measure first.
- Statistics and ANALYZE — сбор и персистенция статистики.
- How to read query plans —
EXPLAIN, operators, diagnostics, cache/replan signals. - Parallel runtime observability runbook — DOP-капы, partitioned join.
- jemalloc heap profiling runbook — диагностика памяти.
Observability
- Observability metrics checklist — обязательный минимум метрик.
- Diagnostics bundle runbook — что собирать при инциденте.
Security
- Security operations baseline — security knobs registry, регулярные проверки.
Reference
- Configuration schema reference — все TOML/env параметры с типами и дефолтами.
- Client compatibility baseline — список протестированных клиентов и оговорки.
- Known issues baseline — operator-уровень known issues.
- Operational policies baseline — production-policy baseline.
Troubleshooting
- Troubleshooting guide — типовые инциденты и действия.
- Runbooks index — оглавление всех runbooks.
Validation
- Testing and validation baseline — что проверять перед production.
- Golden dataset management — управление эталонными данными.
- CI reproducibility contract — контракт воспроизводимости сборки.
Ссылки
- Architecture overview — как устроена БД (контекст для эксплуатации).
- Security model — модель безопасности целиком.
- SQL compatibility — границы поддерживаемого SQL.
- Support — как сообщить о проблеме.
Runbooks Index
Каталог операторских runbooks AngaraBase. Все runbooks привязаны к коду и обновляются вместе с release trains.
По категориям
Lifecycle
| Runbook | Когда использовать |
|---|---|
| Upgrade and migration | Перед обновлением версии — pre-flight, rolling, verification |
| MVCC and GC operator minimum | Настройка AngaraGC, диагностика visibility |
Reliability
| Runbook | Когда использовать |
|---|---|
| Backup and restore | Регулярный backup, base/PITR-restore, верификация |
| Disaster recovery playbook | Полная потеря instance, host migration, restore-oracle |
| Replication v2 operations guide | Управление AngaraReplica v2 |
Performance
| Runbook | Когда использовать |
|---|---|
| Performance tuning guide | Точечная оптимизация workload |
| Parallel runtime observability | Диагностика параллельного исполнения, DOP-капы |
| jemalloc heap profiling | Расследование роста памяти |
Observability
| Runbook | Когда использовать |
|---|---|
| Observability metrics checklist | Настройка минимального набора метрик/алертов |
| Diagnostics bundle | Сбор артефактов при инциденте |
| Troubleshooting guide | Симптом → причина → действие |
| Alert runbooks (RM-0.6.3.8 S7) | Per-alert remediation: backing pages для каждого runbook_url в tools/observability/alerts/angarabase_alerts.yaml |
Security
| Runbook | Когда использовать |
|---|---|
| Security operations baseline | Регулярные security checks, knobs registry |
| Hardening | Перевод инстанса в production-ready security configuration |
Reference (operator)
| Документ | Что внутри |
|---|---|
| Configuration schema reference | Полный реестр TOML/env параметров |
| Client compatibility baseline | Протестированные клиенты, известные ограничения |
| Known issues baseline | Operator-уровень known issues |
| Operational policies baseline | Production policy baseline |
Validation
| Документ | Когда использовать |
|---|---|
| Testing and validation baseline | Acceptance-проверки перед production |
| Golden dataset management | Управление эталонными датасетами |
| CI reproducibility contract | Контракт воспроизводимости артефактов |
По симптому (быстрая навигация)
| Симптом | Куда смотреть |
|---|---|
| Сервер не стартует | Troubleshooting → Configuration → Crash recovery |
| Запросы стали медленнее | Performance tuning → Diagnostics → Diagnostics bundle |
Ошибка 0A000 feature_not_supported | SQL compatibility → Known issues |
| Растёт занятый размер на диске | MVCC and GC operator minimum → Diagnostics |
| Растёт RSS / OOM | jemalloc profiling → Configuration |
| Backup или restore завершился ошибкой | Backup and restore → Disaster recovery |
| Аутентификация / RLS / audit ведут себя неожиданно | Security operations → Security model |
| Проблема с клиентом / ORM | Client compatibility → SQL compatibility |
| Подозрение на data corruption | Verify release artifacts → Disaster recovery |
Если runbook не помог
Соберите diagnostics bundle и обратитесь по Support flow.
Дальше
- Troubleshooting guide — индекс симптомов и первых действий.
- Disaster recovery playbook — сценарии «потерян lease / повреждён datadir».
- Diagnostics bundle runbook — как собрать всё необходимое для эскалации одним пакетом.
Alert Runbooks
Operator-facing runbooks для каждого alert правила из
tools/observability/alerts/angarabase_alerts.yaml (RM-0.6.3.8 S7).
Каждый alert содержит annotations.runbook_url со ссылкой на одну из
страниц ниже — это binding между observability surface и operator
remediation path.
Контракт repo-reproducibility (G2-FIX cycle 2 / F-DOC-1): для каждого
runbook_urlв alert YAML существует backing markdown в этом каталоге. Verifier:python3 - <<'PY' import re, pathlib rules = pathlib.Path("tools/observability/alerts/angarabase_alerts.yaml").read_text() slugs = re.findall(r"runbooks/([a-z0-9-]+)", rules) root = pathlib.Path("angarabook/src/operations/runbooks") missing = [s for s in slugs if not (root / f"{s}.md").exists()] print("OK" if not missing else f"MISSING: {missing}") PY
По alert правилам
| Alert | Severity | Runbook |
|---|---|---|
AngarabaseDown | critical | angarabase-down.md |
HighP99Latency | warning | high-p99-latency.md |
HighSlowQueryRatio | warning | high-slow-query-ratio.md |
BufferPoolPressure | warning | buffer-pool-pressure.md |
WALFsyncSlow | warning | wal-fsync-slow.md |
DeadlockSpike | critical | deadlock-spike.md |
LongTransaction | warning | long-transaction.md |
GCBloatHigh | warning | gc-bloat-high.md |
ReplicationLag | warning | replication-lag.md |
IndexRoutingLegacyFallback | warning | index-routing-legacy-fallback.md |
Соглашение об URL
Production angarabook deployment мапит /operations/runbooks/<slug> →
angarabook/src/operations/runbooks/<slug>.md. Если ваш build
использует другой layout, обновите runbook_url в alert YAML
соответственно (источник истины — alert файл, не сами runbooks).
Шаблон новой runbook страницы
Каждая runbook страница содержит:
- Что означает (обязательно) — короткое объяснение alert семантики + PromQL ссылка.
- Severity — critical / warning / info.
- Initial response (≤ 5 минут) — что сделать прямо сейчас.
- Diagnostics — конкретные команды (
curl,psql,iostat, …). - Mitigation — таблица “симптом → действие”.
- Escalation — когда и как эскалировать.
- Связанные — ссылки на смежные runbooks и reference docs.
Связанные
- Runbooks index — общий каталог operator runbooks.
- Observability metrics checklist — minimal набор метрик.
Runbook: AngarabaseDown
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7 (Prometheus Alert Rules v0).
Что означает
Prometheus не получает ответа от target up{job="angarabase"} дольше 30 секунд.
Сервер либо упал, либо не отвечает на /metrics, либо сетевой путь между Prometheus и instance нарушен.
Severity
critical. Затрагивает доступность сервиса для всех клиентов.
Initial response (5 минут)
# 1. Проверить процесс
systemctl status angarabase-server # или ваш service manager
ps -ef | grep angarabase-server
# 2. Проверить порт
ss -ltnp | grep -E ':(5432|9898)'
# 3. Дёрнуть метрики напрямую с хоста
curl -sf http://127.0.0.1:9898/metrics | head -5
Diagnostics
-
Лог сервера:
journalctl -u angarabase-server -n 200(или ваш log path). -
Диагностика crash (RM-0.6.5.6):
- Panic hook: при краше сервер пишет
[PANIC] thread='...' message='...' backtrace:в stderr (обычно перенаправлен вwrapper.log). Ищите backtrace для понимания причины. - Supervisor crash log:
manage.shпишет[CRASH] pid=N exit_code=Mвwrapper.log. Эта строка подтверждает факт падения процесса под управлением супервизора.
Команды для быстрой диагностики:
# Найти последний panic с backtrace (показать 20 строк контекста): grep -A 20 "\[PANIC\]" artifacts/golden_db/logs/wrapper.log | tail -40 # Найти все crash-события с exit кодами: grep "\[CRASH\]" artifacts/golden_db/logs/wrapper.log | tail -10 # Пример вывода: [CRASH] pid=18073 exit_code=101 timestamp=2026-05-07T07:03:57Z # Проверить последние 50 строк лога сервера до краша: grep -B 5 "\[CRASH\]\|\[PANIC\]" artifacts/golden_db/logs/wrapper.log | tail -30 - Panic hook: при краше сервер пишет
-
Lease: см.
crash-recovery.mdесли сервер упал из-заResourceBusy(PID файл / lease). -
Network:
ss -s,iptables -L -n, проверить firewall между Prometheus и instance.
Mitigation
| Сценарий | Действие |
|---|---|
| Процесс упал | systemctl restart angarabase-server + собрать crash dump |
| Lease stuck | ANGARABASE_FORCE_LEASE_TAKEOVER=1 + рестарт (см. troubleshooting.md) |
| Сеть | Проверить firewall, маршрут, DNS |
Перегрузка /metrics | Снизить scrape_interval; проверить timeouts в Prometheus |
Escalation
Если перезапуск не помогает > 10 минут — собрать diagnostics bundle и эскалировать по support flow.
Связанные
Runbook: HighP99Latency
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7.
Что означает
P99 latency запросов превышает 100 ms на протяжении 5 минут.
Метрика: histogram_quantile(0.99, rate(angarabase_query_exec_duration_ms_bucket[5m])).
Severity
warning. Сигнал ухудшения UX, не отказ.
Initial response
- Открыть Grafana dashboard AngaraBase Overview v2 → row “Query Performance”.
- Сравнить с P50/P95 — если все три выросли вместе, это глобальная проблема (CPU/IO/lock); если только P99 — tail latency (GC, fsync stall, single slow query).
- Проверить
slow_query_totalrate — растёт ли число slow queries.
Diagnostics
# Top-N медленных запросов
curl -sf http://127.0.0.1:9898/metrics | rg slow_query_total
curl -sf http://127.0.0.1:9898/metrics | rg query_exec_duration_ms_bucket
# Активные long-running транзакции
psql -c "SELECT pid, age(now(), xact_start), query FROM angara_stat_activity \
WHERE state = 'active' ORDER BY xact_start LIMIT 10;"
Cross-check с другими сигналами: BufferPoolPressure, WALFsyncSlow, LongTransaction.
Mitigation
- План оптимизации: см. performance-tuning.md.
- ANALYZE на горячих таблицах.
- Индексы: проверить
angarabase_index_routing_legacy_total > 0— если да, выполнить DROP+CREATE INDEX (см. index-routing-legacy-fallback). - Buffer pool: hit ratio < 90% → увеличить
buffer_pool_pages.
Escalation
Если latency не снижается после стандартных действий > 30 минут → diagnostics bundle + эскалация.
Связанные
Runbook: HighSlowQueryRatio
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7. Renamed fromHighErrorRateв G2-FIX cycle 2 (F-S7-1, 2026-04-19) чтобы честно отразить семантику.
Что означает
Доля slow-запросов превышает 1 % от общего числа запросов за последние 5 минут:
rate(angarabase_slow_query_total[5m])
/ clamp_min(rate(angarabase_query_exec_total[5m]), 1)
> 0.01
Важно: это НЕ true error rate. AngaraBase пока не разделяет
angarabase_query_exec_totalна_ok / _errcounter’ы (Design Gap DG-1, перенесено в RM-0.6.6.0). Slow-query ratio — best-effort proxy для client-perceived degradation. ИстинныйHighErrorRateпоявится после split’а counter’ов.
Severity
warning. Сигнал деградации, не отказ.
Initial response
- Открыть Grafana Overview v2 → row “Query Performance” → panel “Slow queries / Total queries ratio”.
- Drill-down в Query Store dashboard → top-N slow queries.
- Проверить корреляцию с
BufferPoolPressure,LongTransaction,WALFsyncSlow.
Diagnostics
curl -sf http://127.0.0.1:9898/metrics | rg -E '^angarabase_(slow_query|query_exec)_total'
psql -c "SELECT * FROM angara_stat_statements ORDER BY total_time DESC LIMIT 10;"
Mitigation
| Симптом | Действие |
|---|---|
| Конкретный запрос | EXPLAIN ANALYZE → пересоздать индекс / переписать запрос |
runtime_facts.spill_bytes > 0 | Нехватка памяти для оператора. См. Performance tuning (увеличение memory limit / work_mem) |
seq scan chosen: low cardinality / low selectivity | Ожидаемо при порогах в [execution]. Сначала ANALYZE и distinct_estimate. Затем при необходимости поправьте index_cardinality_threshold / index_scan_selectivity_threshold в angarabase.conf (или env до старта) и сделайте рестарт; SET в Simple Query не применяется. См. Statistics, Performance tuning |
| Все запросы медленнее | См. HighP99Latency — сначала проверить системные сигналы |
| Растёт после deploy | Откатить релиз; проверить план запросов |
| Корреляция с GC | См. GCBloatHigh |
Escalation
Если ratio не падает > 30 минут → diagnostics bundle + эскалация.
Связанные
- Performance tuning guide
- HighP99Latency
- DG-1 split
_ok/_errcounters (RM-0.6.6.0 Specs Backlog)
Runbook: BufferPoolPressure
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7.
Что означает
Buffer pool hit ratio упал ниже 90 % (метрика angarabase_buffer_pool_hit_ratio_milli < 900)
на протяжении 10 минут. Каждое page-чтение всё чаще идёт на диск, а не из памяти.
Severity
warning. Производительность чтений деградирует; ещё не critical.
Initial response
- Grafana Overview v2 → row “Buffer Pool & Memory”.
- Сравнить
pages_loadedrate сpages_evictedrate — есть ли churn. - Проверить
angarabase_jemalloc_resident_bytes— растёт ли RSS (намёк на leak).
Diagnostics
# Текущая ёмкость и загрузка буферного пула (RM-0.6.6.3 S6-D2)
curl -sf http://127.0.0.1:9898/metrics | rg "buffer_pool_capacity|buffer_pool_hit|buffer_pool_miss"
# Пример вывода:
# angarabase_buffer_pool_capacity_pages 195797 ← авто-детект 25% AvailRAM (3.0 GiB)
# angarabase_buffer_pool_hit_total 4120000
# angarabase_buffer_pool_miss_total 380000
curl -sf http://127.0.0.1:9898/metrics | rg buffer_pool
curl -sf http://127.0.0.1:9898/metrics | rg jemalloc
# Top tables by reads
psql -c "SELECT relname, heap_blks_read, heap_blks_hit \
FROM pg_statio_user_tables ORDER BY heap_blks_read DESC LIMIT 10;"
Mitigation
-
Авто-сайзинг (RM-0.6.6.3): начиная с этого релиза движок автоматически определяет размер буферного пула при старте: 25% от
MemAvailable/proc/meminfo, clamp [1.6 GiB, 32 GiB]. Перезапуск после освобождения памяти на хосте часто решает проблему без изменения конфига.Для принудительного значения:
export ANGARABASE_STORAGE_MAX_CACHED_PAGES=<N>перед стартом, где N = количество 16 KiB страниц (например, 200000 ≈ 3.1 GiB). -
Working set > RAM: рассмотреть partition или archival старых данных.
-
GC churn: проверить GCBloatHigh — bloat увеличивает working set.
-
Memory leak: см. jemalloc-profiling.md.
Escalation
Если hit ratio не восстанавливается после изменения config / рестарта — diagnostics bundle.
Связанные
- Performance tuning guide
- Configuration schema reference
- jemalloc profiling
- Backpressure Coordinator (RM-0.6.3.9 §S5+§S9) —
unified pool/WAL/uncommitted-pages backpressure decisions, including
the
pool_wait_timeout_msknob,angarabase_buffer_pool_over_capacity_pages,angarabase_buffer_pool_evict_failed_total,angarabase_buffer_pool_waiter_wait_secondshistogram, and theBufferPoolError::WaitTimeoutSQL error path (RM-0.6.3.9 §S2+§S8 capacity waiter). - Resource Advisors v0 (RM-0.6.3.9 §S10) —
angarabase_memory_pressure_ratiocorrelates with sustainedBufferPoolPressureevents when working-set growth, not churn, is the cause.
Runbook: WALFsyncSlow
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7.
Что означает
P99 fsync latency для WAL превышает 50 ms на протяжении 5 минут. Каждый commit ждёт диска дольше, чем целевой бюджет — TPS падает, commit latency растёт, риск каскадного backlog.
Severity
warning. При 200 ms+ — близко к critical (рассмотреть эскалацию).
Initial response
- Grafana Overview v2 → row “WAL & Durability”.
- Проверить, не выросла ли WAL throughput rate (bytes/s) — переполнение write buffer.
iostat -xm 1 5на хосте — насыщен ли диск под WAL.
Diagnostics
curl -sf http://127.0.0.1:9898/metrics | rg transaction_log
iostat -xm 1 5
dmesg | tail -50 # ошибки I/O / SMART warnings
Mitigation
| Причина | Действие |
|---|---|
| Disk насыщен | Перенести WAL на отдельный диск; SSD/NVMe вместо HDD |
| Group commit off | Включить wal.group_commit = true в config |
| Network FS | НЕ используйте NFS / CIFS для wal/ — fsync семантика непредсказуема |
Большой wal_buffer_bytes | Уменьшить до разумного (16–64 MB) |
| Filesystem barriers off | Проверить mount options (barrier=1, data=ordered) |
Escalation
Если fsync > 200 ms сохраняется > 10 минут — это путь к coordinated omission и потере commit; собрать diagnostics bundle, эскалировать срочно (durability-критично).
Связанные
Runbook: CommitLatencyTuning
Sources of truth:
- RM-0.6.3.10 (Track B S11/S12/S13) — group-commit baseline.
- RM-0.6.4.0 (Sprint 2/3) — WAL contract, SyncAtCommit mode.
Что означает
Runbook для ситуации, когда COMMIT latency выше ожидаемой либо нестабильна между одинаковыми нагрузками (single-client cron jobs, batch DML, mixed RW).
После RM-0.6.4.0 введён режим sync_at_commit (alias strict): каждый COMMIT
принудительно fsync-ирует WAL перед подтверждением. Это добавляет новые режимы
в таблицу ожидаемых latency.
Режимы durability (RM-0.6.4.0+)
Настраиваются через ANGARABASE_TRANSACTION_LOG_DURABILITY (env).
| Режим | Env значение | Характеристика | Применение |
|---|---|---|---|
| Relaxed | relaxed | WAL буферизуется, без fsync per commit | Dev/bench только |
| Group commit | group_commit | WAL pump коалесцирует и fsync по батчу | Production (по умолчанию) |
| Sync at commit | sync_at_commit или strict | fsync на каждом COMMIT | Банки, финансы, max durability |
Важно:
SET [LOCAL] durability = ...иCOMMIT WITH DURABILITY = ...зарезервированы для v0.6.5 и возвращаютSQLSTATE 0A000 feature_not_supported. Для конфигурации используйте env.
Базовые ожидания по latency
| Режим | Условие | Ожидание (ориентир) |
|---|---|---|
relaxed | fsync=false | sub-ms COMMIT; не для production |
group_commit | fsync=false | COMMIT ~0.1–5 ms; батчи сглаживают spikes |
group_commit | fsync=true | COMMIT 2–20 ms; доминирует диск |
sync_at_commit | NVMe | COMMIT 1–5 ms per tx (один fsync) |
sync_at_commit | HDD | COMMIT 5–20+ ms per tx |
Если p50 или p99 существенно выше диапазона, проверяй диагностический блок ниже.
Какие метрики смотреть
Новые метрики RM-0.6.4.0 (WAL Commit-Path)
curl -sf http://127.0.0.1:9898/metrics | rg "wal_commit|wal_durability|wal_barrier"
| Метрика | Смысл |
|---|---|
angarabase_wal_commit_fsync_total | Число fsync вызовов WAL writer (рост = активный sync) |
angarabase_wal_durability_epoch | Монотонный счётчик эпох durability barrier |
angarabase_wal_barrier_wait_total | Число транзакций ожидавших durability barrier |
angarabase_wal_barrier_duration_seconds | Гистограмма времени ожидания barrier |
Базовые метрики (group commit / write path)
curl -sf http://127.0.0.1:9898/metrics | rg "write_path_phase_b|group_commit|transaction_log"
| Метрика | Смысл |
|---|---|
angarabase_write_path_phase_b_duration_seconds | Гистограмма фазы B (commit hot-path) |
angarabase_write_path_phase_b_timeout_total | Таймауты фазы B — должен быть низким |
angarabase_group_commit_batches_total | Число батчей pump |
angarabase_group_commit_batch_size | Распределение размеров батча |
angarabase_transaction_log_group_commit_pumps_total | Число прогонов pump |
angarabase_transaction_log_group_commit_pump_duration_ms | Длительность одного pump |
Быстрая диагностика
# Новые WAL метрики (RM-0.6.4.0)
curl -sf http://127.0.0.1:9898/metrics | rg "wal_(commit|durability|barrier)"
# Group commit baseline
curl -sf http://127.0.0.1:9898/metrics | rg "write_path_phase_b|group_commit|transaction_log_group_commit"
# I/O correlate
iostat -xm 1 5
Если iostat показывает высокий await/util и одновременно растут
*_pump_duration_ms и p99 COMMIT, проблема почти всегда в I/O слое.
При sync_at_commit: если angarabase_wal_commit_fsync_total растёт
пропорционально tx rate — режим работает корректно. Если rate несоразмерно высок,
проверить wal_barrier_duration_seconds на наличие stall.
Тюнинг-порядок
- Подтверди режим durability (
ANGARABASE_TRANSACTION_LOG_DURABILITY) и целевой SLA. - Для
sync_at_commit: убедись, что WAL файлы на NVMe / отдельном шпинделе. - Проверь, не ушёл ли workload в burst: сравни tx-rate и batch-size histogram.
- Для production сначала стабилизируй диск, затем подбирай
group_commit_interval_ms. - Для bench/dev допускается
relaxed, но фиксируй это в отчёте.
DML-coverage check
Для triage полезно подтвердить, что latency-аномалия не маскирует regression:
INSERT INTO t(...) VALUES (..., now())— должен успешно проходить.UPDATE t SET x = x + 1 WHERE ...— выражение должно применяться.UPDATE/DELETEв autocommit и в txn должны возвращать корректный row count.
Эскалация
- Если
fsync=trueи p99 COMMIT > 200 ms более 10 минут — эскалировать как durability-risk инцидент. - Если
wal_barrier_duration_secondsp99 > 50 ms приsync_at_commit— проверить I/O stall. - Если
errors_total > 0в TPC-B-lite smoke — стоп на performance claims до устранения correctness.
Связанные
- Runbook: WALFsyncSlow
- Runbook: BufferPoolPressure
- Backpressure runtime settings
- Performance tuning guide
Runbook: DeadlockSpike
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7, RM-0.6.4.4 (SSI).
Что означает
rate(angarabase_deadlock_detected_total[1m]) > 1 — детектор deadlock’ов
сработал чаще одного раза в минуту. Один-два deadlock’а в час — нормально;
spike указывает на проблемный workload pattern.
Для SERIALIZABLE транзакций: всплеск ошибок 40001 (serialization_failure)
может выглядеть как deadlock spike в логах приложения, но имеет другую природу
(rw-антизависимости). См. метрику angarabase_ssi_aborts_total.
Severity
critical. Deadlock = aborted transaction = потенциальная потеря работы клиента.
Для SSI: 40001 — штатный механизм, но высокий rate требует анализа contention.
Initial response
- Grafana Overview v2 → row “Locks”.
- Проверить, какие таблицы участвуют в spike (см. лог сервера на сообщения
deadlock detected: ...). - Сопоставить с recent deploy / migration — новый workload?
Diagnostics
curl -sf http://127.0.0.1:9898/metrics | rg -E 'lock_|deadlock'
journalctl -u angarabase-server -n 500 | rg -i 'deadlock'
# Активные блокировки (если есть совместимый view)
psql -c "SELECT * FROM angara_stat_locks WHERE granted = false;"
Mitigation
| Причина | Действие |
|---|---|
| Разные порядки lock acquisition | Унифицировать порядок (UPDATE по PK ASC) в коде клиента |
| Long-running txn держит lock | См. LongTransaction |
| Hot row contention | Шардирование счётчика; sequence вместо UPDATE |
| Конкретный код — обновить | Откатить deploy, исправить, redeploy |
Escalation
Если spike не утихает > 15 минут — это блокирует бизнес-операции, эскалировать срочно.
Связанные
Runbook: LongTransaction
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7, RM-0.6.4.4 (SSI).
Что означает
angarabase_txn_oldest_snapshot_age_seconds > 300 — самая старая открытая транзакция
живёт уже более 5 минут. Это блокирует MVCC GC и приводит к bloat.
Для SERIALIZABLE транзакций: длительное удержание транзакции также блокирует очистку (GC) SIREAD-блокировок и графа конфликтов SSI, что может привести к росту ложных прерываний (false positive aborts 40001) для новых транзакций из-за эскалации блокировок.
Severity
warning. При 30+ минутах превращается в реальный блокер для GC.
Для SSI workloads — критично для производительности (throughput) из-за абортов.
Initial response
- Grafana Overview v2 → row “GC / MVCC”.
- Найти PID транзакции:
SELECT pid, age(now(), xact_start) AS age, state, query
FROM angara_stat_activity
WHERE state IN ('idle in transaction', 'active')
ORDER BY xact_start ASC LIMIT 5;
Diagnostics
curl -sf http://127.0.0.1:9898/metrics | rg -E 'txn_(oldest_snapshot|active|idle)'
curl -sf http://127.0.0.1:9898/metrics | rg gc_
Mitigation
| Причина | Действие |
|---|---|
Клиент завис в idle in transaction | Включить idle_in_transaction_session_timeout |
| Долгая аналитическая выборка | Перенести на read-replica; разбить на batched |
| Pgbouncer пул | Проверить server_idle_timeout, рестартовать pool |
| Application bug | Исправить на стороне клиента (transaction scope) |
Принудительный abort (последняя мера):
SELECT pg_terminate_backend(<pid>);
Escalation
Если транзакция > 1 часа и блокирует GC до bloat > 30% — рассмотреть terminate + escalation, документировать инцидент.
Связанные
Runbook: GCBloatHigh
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7.
Что означает
angarabase_gc_tuning_bloat_ratio_percent > 50 — на одну “живую” версию приходится
больше одной “мёртвой” (которую AngaraGC не может удалить). Чаще всего это симптом
блокирующей долгой транзакции (см. LongTransaction).
Severity
warning. При 80+ % bloat hit ratio buffer pool падает.
Initial response
- Grafana Overview v2 → row “GC / MVCC”.
- Проверить
LongTransactionалерт — обычно root cause там. - Проверить
gc_tuning_state— auto-tuning сам реагирует или нет.
Diagnostics
curl -sf http://127.0.0.1:9898/metrics | rg gc_
curl -sf http://127.0.0.1:9898/metrics | rg mvcc_
# Top tables by bloat
psql -c "SELECT schemaname, relname, n_dead_tup, n_live_tup,
round(100.0 * n_dead_tup / NULLIF(n_live_tup,0), 2) AS bloat_pct
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY bloat_pct DESC NULLS LAST LIMIT 10;"
Mitigation
- Закрыть длинные транзакции — см. LongTransaction.
- Запустить vacuum на горячих таблицах.
- Настроить GC — увеличить агрессивность auto-tuning (см. mvcc-gc.md §Knobs).
- Полный rebuild (downtime) если bloat > 70 % и vacuum не помогает.
Escalation
Если bloat > 70 % и не падает после vacuum + закрытия long txns — собрать diagnostics и эскалировать (потенциально нужен сервисный downtime).
Связанные
Runbook: ReplicationLag
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S7.
Что означает
Задержка реплики (angarabase_replication_lag_bytes или эквивалент в seconds) > 10 секунд.
Реплика отстаёт от primary; чтения с реплики возвращают устаревшие данные.
Severity
warning. При > 60 секунд риск потери данных при failover.
Initial response
- Grafana Overview v2 → row “Replication”.
- На primary: проверить slot status / sender backpressure.
- На реплике: проверить apply rate / disk space / network bandwidth.
Diagnostics
# Primary
curl -sf http://primary:9898/metrics | rg replication
# Replica
curl -sf http://replica:9898/metrics | rg replication
# Application lag в секундах
psql -h replica -c "SELECT now() - pg_last_xact_replay_timestamp() AS apply_lag;"
См. также replication-v2.md §Diagnostics.
Mitigation
| Причина | Действие |
|---|---|
| Сеть | Проверить bandwidth, RTT, packet loss между primary и replica |
| Реплика медленнее primary | Upgrade hardware (SSD, CPU, RAM) на replica |
| Большой slot backlog | Освободить (рискованно — drop неактивный slot) |
| Apply bottleneck (single-threaded) | См. replication-v2.md §Tuning |
| Конкурент GC на реплике | Снизить query load на replica |
Escalation
Если lag > 60 секунд и растёт > 15 минут — оценить риск split-brain при failover; подготовить план восстановления.
Связанные
Runbook: IndexRoutingLegacyFallback
Source of truth:
tools/observability/alerts/angarabase_alerts.yaml. Backed by: RM-0.6.3.8 S5 + S7. Synergy alert: binds Track 1 storage-correctness counter to Track 2 alerting layer.
Что означает
angarabase_index_routing_legacy_total{db="<db>"} > 0 post-upgrade — на этом instance
существуют secondary индексы, чьи catalog записи (IndexDef.index_db_name) ещё не содержат
owning DB. Они корректно работают через legacy fallback на base.adb, но это означает:
- индекс физически живёт в
base.adbвместо<db>.adb, - backup только
<db>.adbпотеряет такой индекс на restore, - RFC-2026-087 §4.1 invariant (per-DB co-location of pages) нарушен.
Severity
warning. Не critical — данные не теряются и индекс работает, но требует миграции.
Why this alert fires after upgrade
RM-0.6.3.8 ввёл per-DB IndexStore page routing. Бинарь до RM-0.6.3.8 создавал
IndexDef без поля index_db_name. После upgrade такие индексы расшифровываются
с index_db_name = None и попадают на legacy путь, инкрементируя этот counter.
Initial response
# Какие БД содержат legacy индексы
curl -sf http://127.0.0.1:9898/metrics | rg index_routing_legacy_total
# Список индексов на проблемной БД
psql -d <db> -c "SELECT schemaname, tablename, indexname FROM pg_indexes \
WHERE schemaname NOT IN ('pg_catalog','information_schema');"
Mitigation: DROP + CREATE INDEX
Для каждого затронутого индекса выполнить (в окне обслуживания):
\c <db>
DROP INDEX IF EXISTS public.<index_name>;
CREATE INDEX <index_name> ON public.<table> (<col>);
После повторного создания counter перестаёт расти (старая запись IndexDef заменяется
новой с корректным index_db_name = Some("<db>"), страницы пишутся в <db>.adb).
Verification
# Counter не должен расти после миграции
watch -n 30 'curl -sf http://127.0.0.1:9898/metrics | rg index_routing_legacy_total'
И проверить размер per-DB файла:
ls -lh <datadir>/<db>.adb
ls -lh <datadir>/base.adb # должен ужаться после переезда индексов
Escalation
Не требуется — это плановая миграция, не инцидент. Если counter растёт без upgrade’а — это баг, эскалировать.
Связанные
- Backup and restore — почему legacy индексы ломали backup
- Upgrade and migration
- RFC-2026-087 §4.1 + Addendum §S2 (RM-0.6.3.8)
Troubleshooting Guide
Этот документ переносит в AngaraBook ключевой операторский fast-path из legacy troubleshooting runbook.
Scope
Покрываются типовые эксплуатационные инциденты AngaraBase и быстрые действия для диагностики/ремедиации.
Связанные документы:
Incident: False Positive Commit Conflicts (40001)
Symptoms
- Клиенты получают
SQLSTATE 40001на каждой попыткеCOMMIT. - В логах старта возможны warning из recovery.
Typical causes
- Версия ниже фикс-релиза для VLF recovery path.
- Перепутаны
data_directoryиtransaction_log_directory.
Actions
- Обновить версию до фиксированной.
- Разделить
storage.data_directoryиstorage.transaction_log_directory.
Incident: Backpressure active (no-steal)
Symptoms
buffer_pool_backpressure_active == 1- Растут
buffer_pool_uncommitted_dirty_ratioиtxn_write_set_limit_exceeded_total
Actions
- Уменьшить batch size write-транзакций.
- При необходимости включить
buffer_pool.backpressure.mode = fail_fast. - Снизить
txn.max_write_set_pagesи/или увеличитьbuffer_pool.size_bytes.
Incident: p99 spikes during checkpoint
Symptoms
- Рост
checkpoint_duration_secondsи latency spikes.
Actions
- Увеличить
checkpoint.target_ms. - Ограничить
writeback.max_bytes_per_sec. - Подкрутить
checkpoint.dirty_ratio_hardдля более раннего фонового writeback.
Incident: commit fsync tails / durable_lsn lag grows
Symptoms
- Рост
commit_ack_latency_secondsиdurable_lsn_lag_bytes.
Actions
- По возможности вынести WAL/TL на отдельный volume.
- Настроить
group_commit.max_wait_us. - Снизить writeback interference.
Start / stop (operator baseline)
angarabase-server --config /etc/angarabase/angarabase.conf
Минимальные проверки перед запуском:
- валидный конфиг;
- корректные каталоги data/txn log;
- достаточные лимиты диска и fsync latency budget.
Incident: CRC mismatch in Delete Vector blob
Symptoms
- Query fails with error:
CRC mismatch for DV blob <path> (segment <id>): expected <exp>, got <got> - Возможно при compaction или при применении columnar DELETE.
Что означает
Файл .bdel (Delete Vector blob) повреждён. Поле blob_uri указывает точный путь к файлу, segment_id — идентификатор сегмента внутри blob-а. Ошибка fail-closed: чтение прекращается, данные не изменяются.
Actions
- Найти повреждённый файл по
blob_uriиз сообщения об ошибке. - Проверить целостность storage volume (IO errors в
dmesg, S.M.A.R.T.). - Если файл повреждён безвозвратно — выполнить restore из backup (
disaster-recovery.md). - При повторяющихся CRC ошибках — включить мониторинг
angarabase_columnar_pending_deleted_rowsдля отслеживания DV fragmentation pressure.
Triage fast-path
- Проверить версию бинарника и активный конфиг.
- Снять базовые метрики (
commit_ack_latency, checkpoint, backpressure). - Проверить состояние recovery/txn log.
- Применить remediation по соответствующему инциденту.
Расширенные связанные материалы:
Дальше
- Diagnostics bundle runbook — что приложить к тикету, если симптом не сводится к runbook.
- Disaster recovery playbook — для случаев потери lease или corrupted datadir.
- Performance tuning guide — если симптом — деградация, а не отказ.
- Operations overview — навигация по остальным operator-материалам.
Disaster Recovery Playbook
Базовый DR playbook на случай, когда штатный recovery path не закрывает инцидент.
Каноничный источник: этот runbook в angarabook/src/operations/.
Scope
Покрывает минимальные сценарии:
- повреждение WAL;
- потеря data directory;
- emergency-режимы с осознанным риском.
1) Corrupted WAL
Symptoms
ChecksumMismatchилиInvalidRecordпри старте.
Actions
- Если повреждение в tail, ожидать штатный truncate/recovery path.
- Если повреждение в середине:
- приоритетно restore из валидного backup (см. Backup and restore);
- emergency truncate допустим только как last resort с риском потери транзакций.
2) Lost data directory
Actions
- Восстановить
data_directoryиз full backup (процедура — Backup and restore). - Проверить, что WAL содержит непрерывную цепочку после точки backup.
- Запустить replay и подтвердить консистентность проверками.
3) Emergency modes (high risk)
- Игнор/ослабление проверок целостности допустимо только как break-glass.
- Любой такой запуск требует явного incident evidence и пост-инцидентного восстановления в штатный режим.
4) Prevention baseline
- Регулярные проверенные backup/restore rehearsal.
- Atomic snapshots data+txlog при использовании snapshot стратегии.
- Наличие pinned evidence для последних упражнений DR.
Дальше
- Backup and restore (operator-level) — какие предварительные снапшоты должны быть для DR-сценариев.
- Upgrade and migration — пересечение с DR при cross-version миграции.
- Replication v2 operations guide — как DR строится поверх логической репликации.
- Troubleshooting guide — если DR-процедура застряла на конкретной фазе.
Performance Tuning Guide
Операторский baseline по performance tuning для early releases.
Каноничный источник: этот runbook в angarabook/src/operations/.
Scope
Фокус:
- buffer pool / checkpoint / writeback;
- TL/WAL durability и group commit;
- no-steal guardrails для больших транзакций.
Core principle (MVP)
MVP использует no-steal:
- uncommitted страницы не flush на диск;
- корректность recovery упрощается, но нужны жесткие guardrails по write pressure.
Quick profiles
OLTP (short transactions)
durability = sync_at_commit(strict) для максимальной надёжности, илиgroup_commitс маленькимgroup_commit.max_wait_usдля меньшей latency.- Консервативные лимиты
txn.max_write_set_pages. buffer_pool.backpressure.mode = blockдля предсказуемого поведения.
Analytics / long queries
- Допустим более высокий write set ceiling.
buffer_pool.backpressure.mode = fail_fast, если приоритет latency/SLO.- Усиленный контроль tail latency commit при
group_commit.
Storage Compression (RM-0.6.4.8+)
- Сжатие страниц (Page Compression) включается через
CREATE TABLE ... WITH (compression='lz4'). - При интенсивном чтении сжатых страниц следите за метрикой
angarabase_buffer_pool_decomp_spill_total. Если она растет, возможно, стоит ограничить concurrency или увеличить ресурсы. - В случае сбоя сжатия при вытеснении страницы (eviction), система откатывается к записи без сжатия (fail-open) и инкрементирует
angarabase_compression_downgrade_total.
SIMD Float Aggregation (RM-0.6.6.5)
- Агрегатные функции
SUM(float4)иSUM(float8)автоматически используют SIMD инструкции (AVX2 или NEON) при наличии поддержки процессором. - Это значительно ускоряет аналитические запросы над числами с плавающей точкой.
- Если SIMD недоступен, система прозрачно переходит на скалярную реализацию, инкрементируя метрику
angarabase_simd_agg_fallback_total.
Adaptive Hash-Join (RM-0.6.6.5)
- Планировщик автоматически меняет местами стороны Build и Probe в Hash Join, если фактическое отношение их размеров превышает порог
adaptive_hash_join_swap_ratio(по умолчанию 4). - Это позволяет использовать меньшую таблицу для построения хэш-таблицы, экономя память и уменьшая вероятность сброса на диск (spill).
- Факт переключения фиксируется в метрике
angarabase_adaptive_probe_swap_total.
Snapshot Age Dampening и производительность JOIN
При длинных транзакциях (snapshot age > ANGARABASE_STATS_DRIFT_MAX_AGE_MS, default 30s)
планировщик автоматически пропускает HashJoin в пользу spill-safe стратегии.
Это может снижать производительность JOIN-запросов внутри долгих транзакций.
Рекомендации:
- Для долгих аналитических транзакций: увеличить
ANGARABASE_STATS_DRIFT_MAX_AGE_MSили установить в0для отключения (если статистика актуальна). - Следить за
angarabase_optimizer_drift_fallback_total— резкий рост указывает на долгие транзакции с устаревшими снапшотами. - Запускать
ANALYZEрегулярно для поддержания актуальности статистики.
Dev / test
- Допустим
durability = relaxed(осознанно). txn.statement_timeout_ms = 0.fail_fastполезен для раннего обнаружения перегрузки.
Knobs (MVP list)
durability = sync_at_commit|strict|group_commit|relaxed(env:ANGARABASE_TRANSACTION_LOG_DURABILITY)sync_at_commit/strict— fsync на каждом COMMIT (max durability, RM-0.6.4.0)group_commit— pump коалесцирует fsync (default, production)relaxed— без fsync (dev/bench только)
group_commit.max_batch_sizegroup_commit.max_wait_uscheckpoint.interval_mscheckpoint.target_mscheckpoint.dirty_ratio_soft|hardwriteback.max_bytes_per_sectxn.max_write_set_pages|bytesbuffer_pool.uncommitted_pages_ratio_hard(RM-0.6.3.9 §S5+§S9 rename; old name removed without alias)buffer_pool.backpressure.mode = block|fail_fast[execution].index_cardinality_threshold(по умолчанию 0.15, env:ANGARABASE_INDEX_CARDINALITY_THRESHOLD)- Если селективность предиката строго выше этого порога, индексный скан по одиночному ключу отклоняется (
seq scan chosen: low cardinality).
- Если селективность предиката строго выше этого порога, индексный скан по одиночному ключу отклоняется (
[execution].index_scan_selectivity_threshold(по умолчанию 0.05, env:ANGARABASE_INDEX_SCAN_SELECTIVITY_THRESHOLD)- Если селективность не ниже этого порога, индексный скан также отклоняется (
seq scan chosen: low selectivity). - На смешанных OLTP-нагрузках фильтр может давать ~10–15% строк: кардинальный порог уже пропускает план, а порог селективности 0.05 — нет; тогда повысьте
index_scan_selectivity_threshold(например до 0.15) в конфиге и перезапустите процесс.
- Если селективность не ниже этого порога, индексный скан также отклоняется (
[execution].late_materialization_selectivity_threshold(по умолчанию 0.3, env:ANGARABASE_LATE_MATERIALIZATION_SELECTIVITY_THRESHOLD)- Порог селективности для включения узла
LateMaterialize. Если фильтр пропускает меньше 30% строк, включается отложенная материализация колонок.
- Порог селективности для включения узла
[execution].adaptive_hash_join_swap_ratio(по умолчанию 4.0, env:ANGARABASE_ADAPTIVE_HASH_JOIN_SWAP_RATIO)- Коэффициент для адаптивного переключения сторон в Hash Join. Если отношение размеров сторон (probe/build) становится ≥ 4, стороны меняются местами для оптимизации потребления памяти.
- Меняются только через файл конфигурации (
angarabase.conf, секция[execution]) или env до старта процесса; затем обязателен рестарт сервера. SET optimizer.*/ обычныйSET ...в Simple Query protocol не меняют планировщик: pgwire возвращает успешныйCommandComplete, но значение не применяется (совместимость с клиентами). Для проверки гипотезы используйте правку конфига или env и рестарт.
Symptoms -> actions (fast path)
- Checkpoint p99 spikes: увеличить
checkpoint.target_ms, ограничитьwriteback.max_bytes_per_sec. - Frequent backpressure: уменьшить batch size, снизить
txn.max_write_set_pages, при необходимости увеличить buffer pool. - durable_lsn lag / commit tails: проверить fsync latency, подстроить
group_commitпараметры. - Slow query / plan changed: снять
EXPLAIN (VERBOSE, DIAGNOSTIC)и читать план по How to read query plans. - Unexpected SeqScan на большой таблице: прочитайте
scan_strategy_reason. Дляlow cardinalityпри необходимости снизьте[execution].index_cardinality_threshold; дляlow selectivity— повысьте[execution].index_scan_selectivity_threshold. Сначала проверьте статистику (ANALYZE,distinct_estimate). После смены порогов — рестарт.
Must-have alerts
buffer_pool_backpressure_active == 1дольше порога.buffer_pool_uncommitted_dirty_ratioвыше hard-limit.- Рост
txn_write_set_limit_exceeded_total. - GC/watermark stall (по SLO проекта).
Дальше
- How to read query plans — как читать
EXPLAIN, cost/rows,Vector*,replan_reason,cache_statusиreason_codes. - Observability metrics checklist — что обязательно мерить до и после изменений тюнинга.
- Parallel runtime observability runbook — для CPU-bound нагрузок и DOP-капов.
- jemalloc heap profiling runbook — если узкое место — память, а не CPU.
- MVCC and GC operator minimum — если рост latency коррелирует с GC backlog.
How to Read Query Plans
Этот guide помогает DBA/SRE читать EXPLAIN в AngaraBase без знания
внутреннего кода планировщика. Цель не в том, чтобы вручную «переиграть»
optimizer, а в том, чтобы быстро ответить на операторские вопросы:
- какой путь выполнения выбрала база;
- почему был выбран именно он;
- использует ли запрос векторный/параллельный путь;
- переиспользован ли план из кэша или был перестроен;
- где искать причину высокой latency.
Quick Start
Для обычного плана:
EXPLAIN SELECT * FROM public.orders WHERE customer_id = 42;
Для операторской диагностики:
EXPLAIN (DIAGNOSTIC)
SELECT * FROM public.orders WHERE customer_id = 42;
Для подробного вывода:
EXPLAIN (VERBOSE, DIAGNOSTIC)
SELECT * FROM public.orders WHERE customer_id = 42;
Для machine-readable evidence:
EXPLAIN (VERBOSE, DIAGNOSTIC, FORMAT JSON)
SELECT * FROM public.orders WHERE customer_id = 42;
Если нужно увидеть runtime-счётчики, используйте EXPLAIN ANALYZE.
Он выполняет запрос, поэтому для DML используйте его осторожно и только
в безопасном окружении.
Runtime Facts
В режиме ANALYZE AngaraBase собирает дополнительные факты о выполнении запроса
в блоке runtime_facts. Этот блок появляется, если запрос столкнулся с
ожиданиями, сбросом данных на диск (spill) или отклонением из-за лимитов ресурсов.
Пример JSON вывода:
"runtime_facts": {
"spill_bytes": 4096,
"wal_sync_wait_ms": 12,
"resource_reject_count": 1,
"last_runtime_reason": "spilled_memory_budget"
}
Пример текстового вывода:
runtime_facts: spill_bytes=4096 wal_sync_wait_ms=12 resource_reject_count=1 last_runtime_reason=spilled_memory_budget
Основные поля:
spill_bytes— объем данных, сброшенных на диск (например, при нехватке памяти для HashJoin или Sort).wal_sync_wait_ms— время ожидания синхронизации WAL. (Может быть не выведено дляSELECT, приdurability=relaxed, или если транзакция успешно попала в групповой коммит без дополнительного ожидания I/O).resource_reject_count— количество отклонений из-за лимитов ресурсов.last_runtime_reason— код причины, напримерspilled_memory_budget.
Примечание: выводятся только поля с ненулевыми значениями.
Как читать дерево
План читается снизу вверх. Нижний оператор получает данные из таблицы или индекса. Каждый следующий оператор выше применяет фильтр, join, агрегацию, сортировку или projection.
Пример:
Project cost=0.00..1030.00 rows=100
VectorFilter cost=0.00..1025.00 rows=100
VectorSeqScan workers_planned=2 workers_launched=2 numa_affinity=disabled table=public.ux_stats_v2 cost=0.00..1000.00 rows=1000
--- Optimizer Diagnostics ---
query_fingerprint=1795416667712787713
plan_fingerprint=3192678580981205807
workload_class=select
replan_reason=none
cache_status=hit
reason_codes=stats_default_fallback
Читаем так:
VectorSeqScanчитает таблицуpublic.ux_stats_v2.VectorFilterприменяет условиеWHERE.Projectоставляет нужные колонки в результате.- Блок
Optimizer Diagnosticsобъясняет идентификаторы запроса/плана, кэш, причину перепланирования и reason codes.
Формат строки оператора
Разберём строку:
VectorSeqScan workers_planned=2 workers_launched=2 numa_affinity=disabled table=public.ux_stats_v2 cost=0.00..1000.00 rows=1000
| Поле | Что означает | Как читать оператору |
|---|---|---|
VectorSeqScan | Тип оператора. Vector = векторный executor, SeqScan = последовательное чтение таблицы. | Читаем всю таблицу пачками. Хорошо для full scan / analytics, плохо для точечного lookup на большой таблице без индекса. |
workers_planned=2 | Сколько worker-ов планировщик хотел использовать. | План допускает параллелизм. |
workers_launched=2 | Сколько worker-ов реально выделено. | Если меньше planned, возможны runtime pressure или лимиты параллелизма. |
numa_affinity=disabled | Включена ли привязка к NUMA-node. | Обычно disabled нормально для dev/cloud; на bare metal может быть отдельным tuning-вопросом. |
table=public.ux_stats_v2 | Таблица-источник. | Проверяем, что сканируется ожидаемая таблица/схема. |
cost=0.00..1000.00 | startup_cost..total_cost в условных единицах планировщика. | Это не миллисекунды. Сравнивайте с альтернативными планами, а не с wall-clock. |
rows=1000 | Оценка количества строк на выходе оператора. | Сильная ошибка оценки часто ведёт к плохому join order или лишнему full scan. |
Cost и Rows
cost — это внутренняя оценка работы, а не время выполнения.
startup_cost— цена получить первую строку.total_cost— цена получить все строки.rows— ожидаемое количество строк после оператора.
Типичная ошибка: читать cost=1000 как 1000 ms. Так делать нельзя.
Cost нужен optimizer-у для сравнения вариантов:
- full scan vs index scan;
- hash join vs nested/index join;
- сортировать до или после фильтра;
- выполнять aggregate над всеми строками или над уже отфильтрованным input.
Если rows явно не похож на реальность, сначала проверьте статистику:
ANALYZE public.orders;
SELECT *
FROM sys.table_stats
WHERE schema_name = 'public' AND table_name = 'orders';
SELECT *
FROM sys.column_stats
WHERE schema_name = 'public' AND table_name = 'orders';
Vector Prefix
Операторы с префиксом Vector выполняются через векторизованный путь:
VectorSeqScanVectorIndexScanVectorFilterVectorProjectVectorWindowFunctionVectorSetOperation
Векторный путь обрабатывает данные пачками, снижая overhead на строку. Для оператора это обычно хороший признак, особенно на scan/filter/aggregate workload.
Если ожидаемый Vector* исчез:
- Проверьте query shape: не добавили ли выражение, которое пока не поддерживается vector executor-ом.
- Сравните
EXPLAIN (VERBOSE, DIAGNOSTIC)до/после изменения запроса. - Смотрите
reason_codesи плановые node types. - Для latency-регрессий используйте Performance tuning guide и Parallel runtime observability runbook.
Словарь операторов
| Оператор | Что делает | Когда хорошо | Когда подозрительно |
|---|---|---|---|
Scan / VectorSeqScan | Читает таблицу целиком. | Маленькая таблица, аналитика, низкая селективность фильтра. | Точечный lookup на большой таблице, где должен быть индекс. |
IndexScan / VectorIndexScan | Читает через индекс, затем при необходимости проверяет residual filter. | Селективный predicate по индексной колонке. | Если возвращает большую долю таблицы, full scan может быть дешевле. |
IndexOnlyScan | Читает только индекс, без heap fetch, если visibility map позволяет. | Coverage index + all-visible страницы. | Если часто fallback на heap, проверьте visibility map / vacuum-like процессы. |
Filter / VectorFilter | Применяет WHERE/predicate к входному потоку. | После scan/index scan. | Если фильтр стоит выше дорогого join, проверьте pushdown. |
Project / VectorProject | Выбирает/вычисляет выходные колонки. | Обычный верхний оператор для SELECT. | Обычно не проблема, кроме очень дорогих выражений. |
Join | Общий join node с kind=inner/left/right/full/cross. | Ожидаемый join type соответствует SQL. | cross почти всегда требует внимания. |
HashSemiJoin | Реализация EXISTS/semi join через hash. | Хороший знак для декоррелированного EXISTS. | Если ожидали semi join, но видите nested/cross-like план. |
HashAntiJoin | Реализация NOT EXISTS/anti join через hash. | Хороший знак для anti-semi workload. | Если input большой и нет memory headroom. |
NLIndexJoin | Nested-loop probe по индексу. | Малый outer input + селективный index lookup. | Большой outer input: может превратиться в много index probes. |
Aggregate | COUNT, SUM, GROUP BY и другие aggregate операции. | После фильтра или join с уже уменьшенным input. | Если aggregate вынужден материализовать огромный input. |
Sort | Сортирует поток. | Для ORDER BY, merge-like paths. | Большой sort без LIMIT или без индекса по order key. |
Distinct | Удаляет дубликаты. | Нужен для DISTINCT. | На большом input без предварительного сокращения строк. |
Limit / Offset | Ограничивает или пропускает строки. | LIMIT может резко снизить total cost. | Большой OFFSET всё равно заставляет читать/пропускать много строк. |
WindowFunction | Оконные функции. | Аналитические запросы. | Если требует большой sort/partition. |
SetOperation | UNION, INTERSECT, EXCEPT. | Set queries. | Если unexpectedly дорогой из-за dedup/sort. |
LateralJoin | LATERAL/derived-table dependent path. | Коррелированные derived inputs. | На больших outer inputs может быть дорогим. |
LateMaterialize | Отложенная материализация колонок. Читает только необходимые для фильтрации колонки, а остальные дочитывает позже для строк, прошедших фильтр. | Высокая селективность фильтра (selectivity < 0.3). | Если селективность низкая, двойное чтение может быть дороже обычного. |
DmlInsert / DmlUpdate / DmlDelete | Sentinel для DML. | EXPLAIN DML показывает intent. | Для runtime counters используйте EXPLAIN ANALYZE осторожно. |
Ddl | Sentinel для DDL. | Показывает DDL path. | Не является query performance hot path. |
Scan Strategy Reason
Для узлов Scan (SeqScan) и IndexScan планировщик выводит причину выбора
конкретной стратегии сканирования в поле scan_strategy_reason. Это помогает
понять, почему optimizer предпочел последовательное сканирование индексному
или наоборот.
Примеры вывода:
index scan: high selectivity (0.0005)— выбран индекс, так как условие очень селективно.seq scan chosen: low cardinality (0.1328)— выбран SeqScan: селективность выше порога[execution].index_cardinality_threshold(планировщик считает колонку «слишком низкой кардинальности» для индекса на этом предикате).seq scan chosen: low selectivity (0.1111)— выбран SeqScan: селективность не ниже порога[execution].index_scan_selectivity_threshold(отдельный гейт после кардинального).
Если вы видите seq scan chosen там, где ожидали индекс:
- Проверьте актуальность статистики (
ANALYZE). - Проверьте значение
distinct_estimateвsys.column_stats. - Подстройте пороги в
angarabase.conf([execution]) или через env до старта (ANGARABASE_INDEX_CARDINALITY_THRESHOLD,ANGARABASE_INDEX_SCAN_SELECTIVITY_THRESHOLD), затем перезапустите сервер.SET ...из psql в Simple Query protocol не меняет эти knob (см. Performance tuning).
Optimizer Diagnostics
EXPLAIN (DIAGNOSTIC) добавляет блок:
--- Optimizer Diagnostics ---
query_fingerprint=1795416667712787713
plan_fingerprint=3192678580981205807
workload_class=select
replan_reason=none
cache_status=hit
reason_codes=stats_default_fallback
query_fingerprint
Стабильный идентификатор логической формы запроса. Значения литералов обычно не должны создавать новый fingerprint для каждой константы.
Используйте его, чтобы связать:
- slow query;
- метрики;
- логи;
- повторный
EXPLAIN; - regression evidence.
plan_fingerprint
Идентификатор формы плана. Если запрос тот же, но план изменился,
query_fingerprint останется тем же, а plan_fingerprint поменяется.
Это полезно при расследовании:
- «после
ANALYZEзапрос стал быстрее/медленнее»; - «после добавления индекса план поменялся»;
- «вчера был
IndexOnlyScan, сегодня сноваSeqScan».
workload_class
Класс workload-а:
selectwriteddl- другие классы, если конкретный путь их маркирует.
Оператору это помогает отделить OLTP read path от write/DDL событий.
replan_reason
Почему план был перестроен или почему явной причины нет.
| Значение | Смысл | Что делать |
|---|---|---|
none | Явной причины перепланирования нет. Обычно это нормальный путь. | Если cache_status=hit, кэш работает. |
stats_drift | Статистика изменилась достаточно сильно, старый план мог устареть. | Проверить частоту ANALYZE, churn таблицы, стабильность latency. |
schema_changed | Схема изменилась: DDL, индекс, колонка или другой schema signal. | Нормально после миграций; подозрительно при частом DDL в production. |
aqp_feedback | Runtime feedback повлиял на оценку/планирование. | Проверить AQP metrics и skew workload. |
forced_fallback | Planner/runtime выбрал безопасный fallback. | Сравнить reason codes и unsupported expressions. |
cache_status
Показывает отношение запроса к plan cache.
| Значение | Смысл | Как интерпретировать |
|---|---|---|
hit | План переиспользован. | Хорошо для стабильного OLTP. |
miss | План построен заново. | Нормально для первого запуска или нового query shape. |
bypass | Кэш сознательно не использован. | Проверить DDL, volatile shape, diagnostics mode или safety path. |
invalidated | Старый план сброшен. | Ищите replan_reason. |
unknown | Runtime не передал статус. | Не делайте выводов о кэше только по этому полю. |
reason_codes
Причины выбора или fallback-а в планировщике.
| Код | Смысл | Что проверить |
|---|---|---|
stats_default_fallback | Планировщик не смог использовать детальную статистику и применил defaults. | Выполнить ANALYZE, проверить sys.table_stats и sys.column_stats. |
index_only_eligible | План может читать только индекс без heap fetch. | Проверить visibility map и покрытие индекса. |
bitmap_candidate_rejected | Был альтернативный bitmap-like/index path, но выбран другой путь или residual filter. | Сравнить селективность predicate и наличие подходящего индекса. |
hash_join_fits_work_mem | Hash join считается допустимым по памяти. | При p99 росте проверять memory pressure и join cardinality. |
used_multicol_stats | Использована multi-column статистика. | Хороший знак для коррелированных predicate-ов. |
Если reason_codes пустой, AngaraBase показывает stats_default_fallback,
чтобы оператор не получил «молчаливый» diagnostic block.
JSON Format
Для CI, evidence pack и diff между релизами используйте JSON:
EXPLAIN (VERBOSE, DIAGNOSTIC, FORMAT JSON)
SELECT * FROM public.orders WHERE customer_id = 42;
В JSON те же сущности представлены как поля:
Node TypeStartup CostTotal CostPlan RowsPlansworkers_plannedworkers_launchednuma_affinityquery_fingerprintplan_fingerprintreplan_reasonreason_codescache_status
Для release evidence сравнивайте не весь JSON byte-for-byte, а устойчивые свойства: node class, join type, fingerprints, reason codes и ключевые оценки.
Типовые сценарии чтения
1. Медленный точечный lookup
Симптом:
VectorSeqScan table=public.orders ... rows=1000000
Что проверить:
- Есть ли индекс по колонке фильтра.
- Видит ли планировщик статистику (
sys.column_stats). - Не показывает ли diagnostics
stats_default_fallback. - Не слишком ли низкая селективность фильтра.
Желаемый план для точечного lookup обычно ближе к:
IndexScan index_name=... index_col=customer_id key_range=eq(...)
или:
IndexOnlyScan index_name=... index_col=customer_id index_only_reason="..."
2. Отложенная материализация (Late Materialization)
Если фильтр отсекает значительную часть строк, планировщик может выбрать узел LateMaterialize. Это позволяет избежать дорогого чтения всех колонок для строк, которые всё равно будут отфильтрованы.
Порог включения регулируется параметром [execution].late_materialization_selectivity_threshold (по умолчанию 0.3).
Пример плана:
Project cost=10.00..50.00 rows=100
LateMaterialize cost=5.00..45.00 rows=100
VectorFilter (x > 100) cost=0.00..40.00 rows=100
VectorSeqScan table=large_table cost=0.00..30.00 rows=1000
3. EXISTS не должен быть nested-loop
Для запроса:
EXPLAIN (DIAGNOSTIC)
SELECT *
FROM public.orders o
WHERE EXISTS (
SELECT 1
FROM public.order_items i
WHERE i.order_id = o.id
);
Хороший признак:
HashSemiJoin kind=semi on=...
Это значит, что optimizer декоррелировал EXISTS и выбрал hash semi join.
3. NOT EXISTS и anti join
Хороший признак:
HashAntiJoin kind=anti on=...
Если input большой, смотрите hash_join_fits_work_mem и memory metrics.
4. GROUP BY слишком дорогой
Симптом:
Aggregate cost=... rows=...
VectorSeqScan table=...
Что проверить:
- Можно ли отфильтровать строки до aggregate.
- Есть ли лишние projected columns.
- Подходит ли group key под fast path (например, single integer key).
- Не слишком ли много групп.
- Не требует ли запрос сортировки после aggregate.
5. Parallel planned, но latency высокая
Симптом:
workers_planned=2 workers_launched=0
или workers_launched меньше workers_planned.
Что проверить:
- Глобальные лимиты parallel runtime.
- CPU saturation.
- Очереди pgwire/runtime.
- Memory pressure.
- Parallel runtime observability runbook.
6. План поменялся после ANALYZE
Сравните:
query_fingerprint— должен остаться стабильным для той же формы SQL;plan_fingerprint— меняется, если поменялась форма плана;replan_reason— должен объяснить перестроение;reason_codes— покажут, какие новые факторы стали доступны.
Если после ANALYZE появился IndexScan или IndexOnlyScan, это обычно
хороший знак. Если появился SeqScan на большом OLTP lookup, проверьте
selectivity и статистику.
Связь с sys.* views
EXPLAIN показывает план, а sys.* помогает проверить, есть ли у optimizer-а
данные для хорошего решения.
Минимальный набор:
SELECT *
FROM sys.table_stats
WHERE schema_name = 'public' AND table_name = 'orders';
SELECT *
FROM sys.column_stats
WHERE schema_name = 'public' AND table_name = 'orders';
SELECT *
FROM sys.multicolumn_stats
WHERE schema_name = 'public' AND table_name = 'orders';
SELECT *
FROM sys.workload_stats
WHERE schema_name = 'public' AND table_name = 'orders';
Как читать:
row_count_estimateпомогает понять, знает ли optimizer размер таблицы.distinct_estimateпомогает оценивать селективность equality predicate.min_i64/max_i64помогают range predicate-ам.multicolumn_statsпомогает коррелированным условиям.workload_statsпоказывает, как таблица реально используется.
Triage Checklist
Когда пользователь говорит «запрос стал медленным», действуйте так:
-
Снимите план:
EXPLAIN (VERBOSE, DIAGNOSTIC) <query>; -
Если безопасно, снимите runtime:
EXPLAIN ANALYZE <query>; -
Прочитайте дерево снизу вверх.
-
Найдите самый широкий input (
rowsрезко больше ожидаемого). -
Проверьте, используется ли ожидаемый operator class:
IndexScan,IndexOnlyScan,HashSemiJoin,Aggregate,Vector*. -
Проверьте
reason_codes. -
Если есть
stats_default_fallback, выполнитеANALYZEи сравните план. -
Сравните
query_fingerprintиplan_fingerprintдо/после. -
Если проблема в parallel path, переходите к Parallel runtime observability runbook.
-
Если проблема в storage/IO, переходите к Performance tuning guide.
Частые ошибки интерпретации
| Ошибка | Почему неверно | Правильно |
|---|---|---|
cost=1000 значит 1000 ms | Cost — условная модель optimizer-а. | Для времени используйте EXPLAIN ANALYZE и latency метрики. |
SeqScan всегда плохо | Full scan может быть оптимальным для маленьких таблиц или low-selectivity фильтров. | Смотрите размер таблицы, селективность и наличие индекса. |
IndexScan всегда лучше | Index scan может быть хуже full scan, если возвращает большую долю таблицы. | Сравнивайте rows/cost и фактический runtime. |
workers_planned=2 гарантирует ускорение в 2 раза | Worker-и имеют overhead и могут не запуститься. | Смотрите workers_launched и runtime metrics. |
replan_reason=none значит optimizer ничего не сделал | Это значит, что явной причины replan нет. | Смотрите cache_status, fingerprints и reason codes. |
stats_default_fallback можно игнорировать | Это сигнал, что optimizer мог гадать без статистики. | Запустите ANALYZE и проверьте sys.* views. |
Когда эскалировать
Эскалируйте как bug/perf issue, если:
EXPLAIN (DIAGNOSTIC)не показывает diagnostic block (убедитесь, что не используетеEXPLAIN (DIAGNOSTIC ON)— булевый суффиксON/OFFне поддерживается AngaraBase и silently игнорирует опцию; используйтеEXPLAIN (DIAGNOSTIC)без суффикса);query_fingerprintнестабилен для одной и той же формы запроса;plan_fingerprintменяется без schema/stats/AQP причины;replan_reason=stats_driftпоявляется слишком часто на стабильной таблице;IndexOnlyScanвыбран, но runtime постоянно делает heap fetch;HashSemiJoin/HashAntiJoinисчезают для простыхEXISTS/NOT EXISTS;workers_launchedсистемно нижеworkers_plannedбез понятного pressure signal;- JSON/text вывод противоречат друг другу.
Для bug report приложите:
- SQL запроса;
EXPLAIN (VERBOSE, DIAGNOSTIC)text;EXPLAIN (VERBOSE, DIAGNOSTIC, FORMAT JSON);- relevant rows из
sys.table_stats,sys.column_stats,sys.multicolumn_stats,sys.workload_stats; - версию AngaraBase и capability/profile snapshot, если есть.
Дальше
- Performance tuning guide — как действовать после чтения плана, если проблема в latency/throughput.
- Parallel runtime observability runbook — как
расследовать
workers_planned/workers_launchedи runtime pressure. - Observability metrics checklist — какие метрики
сопоставлять с
query_fingerprintиplan_fingerprint. - Diagnostics bundle runbook — как собрать evidence для поддержки.
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
Diagnostics Bundle Runbook
Операторский runbook для быстрого сбора triage-артефактов.
Каноничный источник: этот runbook в angarabook/src/operations/.
Goal
diagnostics bundle должен давать предсказуемый пакет:
- версия и среда запуска;
- базовый on-disk снимок;
- конфиг в redacted-виде;
- метрики и итоговый индекс артефактов.
Pinned commands
CLI (operator-facing, preferred for packaged distribution):
angara-cli diagnostics bundle \
--root artifacts/diagnostics/incident-1 \
--config /etc/angarabase/angarabase.conf \
--data-dir /var/lib/angarabase/data \
--txlog-dir /var/lib/angarabase/transaction_log \
--json
Legacy tools entrypoint (workspace/dev path):
tools/diagnostics_bundle/run.sh --root artifacts/diagnostics/dev
С конфигом и директориями:
tools/diagnostics_bundle/run.sh \
--root artifacts/diagnostics/incident-1 \
--config /etc/angarabase/angarabase.conf \
--data-dir /var/lib/angarabase/data \
--txlog-dir /var/lib/angarabase/transaction_log
Валидация структуры:
tools/diagnostics_bundle/validate.sh <bundle_root>
Artifact layout (minimum)
system.txt,versions.txt,env_angarabase.txton_disk_inspect.jsonconfig.redacted.conf,config_redaction.txtmetrics.prom(илиmetrics.prom.error.txt)summary.jsonok.txt
Security policy
Секреты в конфиге редактируются: значения ключей по шаблонам password, secret, token, api_key
заменяются на "<REDACTED>".
Evidence routing
- Heavy bundle хранится в
artifacts/diagnostics/<stamp>/... - В документации фиксируются только компактные pinned summaries/evidence pointers.
Дальше
- Troubleshooting guide — куда подкладывать собранный bundle.
- Disaster recovery playbook — отдельный набор артефактов для DR-эскалаций.
- Observability metrics checklist — какие метрики дублировать в bundle.
Security Operations Baseline
Краткий операторский security baseline. Расширенный контекст и дополнительные детали находятся в migration history и связных страницах AngaraBook.
Goal
Свести security-relevant knobs в единый операционный контракт:
- безопасные дефолты;
- fail-closed гейты;
- точки наблюдаемости (
sys.settings).
Source of truth
- Config schema:
src/operations/config-schema.md - Runtime settings surfaces:
crates/angarabase/src/settings.rs,crates/angarabase/src/virtual_catalog.rs - Security governance:
src/operations/operational-policies.md
Defaults
server.addr = 127.0.0.1:5152как safe default.- Remote bind запрещен по умолчанию без явного insecure override.
- TLS по умолчанию opt-in; при remote bind политика может требовать TLS fail-closed.
Required fail-closed gates
- Remote bind без
allow_insecureдолжен завершаться отказом старта. - Password auth без TLS должен завершаться отказом старта.
- Изменение настроек в рантайме (
sys.set_setting) требует ролиsession_settings(RM-0.6.4.16).
Knobs registry (operator highlights)
[security] allow_insecure,[security] dev_mode[tls] enabled,[tls] cert_path,[tls] key_path,[tls] require_on_remote_bindANGARABASE_AUTH_MODE,ANGARABASE_TLS_ENABLEANGARABASE_TDE_ENABLE,ANGARABASE_TDE_MASTER_KEY_IDANGARABASE_AUDIT_LOG_PATH,ANGARABASE_AUDIT_DML_MODE
Секреты (например, ANGARABASE_AUTH_PASSWORD, master key) не должны попадать в sys.settings.
Security modes matrix
- Local + strict/group_commit: разрешено.
- Local + relaxed durability: разрешено с warning.
- Remote bind: только с явным override и warning.
- Remote bind + relaxed: только с override, с усиленным warning.
Threat model and evidence
Для threat inventory и evidence pointers использовать:
src/operations/operational-policies.md
Дальше
- Operational policies baseline — где зафиксированы политики, на которые опирается security operations.
- Backup and restore (operator-level) — защита данных как часть SecOps-периметра.
- Disaster recovery playbook — security-инциденты как DR-кейс.
Upgrade and Migration
Ключевой операторский контракт pre-v1 по on-disk формату и процедурам migration.
Goal
Зафиксировать fail-closed правила:
- layout данных и WAL;
- форматные version/magic;
- startup guards;
- обязательные действия при изменении on-disk формата.
Current on-disk layout (as implemented)
- System DB data:
base.adb - System DB WAL:
base.atl - User DB data:
<db_name>.adb - User DB WAL:
<db_name>.atl - Init marker:
VERSION(бинарныйAVR1, CRC32C)
MVCC history хранится в .atl; отдельный mvcc_history.v1.bin больше не создаётся.
Startup behavior (fail-closed)
- non-dev запуск без
VERSION→ reject. - Текстовый legacy
VERSIONне поддерживается. format_versionвыше/ниже поддерживаемого → reject.page_sizeизVERSIONне совпадает с compiledPAGE_SIZE→ reject.
Format identifiers
- Storage page magic/version:
APG1/v3 - WAL record magic/version:
ADB1/v2(v3 planned)
Единый source of truth для magic/version:
crates/angarabase/src/on_disk.rs
Offline migration baseline
Рекомендуемый общий путь:
- Backup старого состояния.
--initв новом формате.- Restore данных.
- Пост-проверки startup и recovery.
In-place migration pre-v1 ограничена и должна выполняться только по документированному runbook-пути.
Upgrade rehearsal
Перед production rollout:
- прогон репетиции обновления на staging;
- фиксация артефактов в evidence;
- проверка rollback-плана.
Подробные процедуры:
src/operations/testing-validation.mdsrc/operations/backup-restore.md
Дальше
- Backup and restore (operator-level) — обязательный шаг до старта апгрейда.
- Disaster recovery playbook — сценарии rollback и восстановления при неудачном апгрейде.
- Replication v2 operations guide — апгрейд в схеме с активной репликацией.
Backup and Restore
Ключевой операторский baseline для backup/restore. Детали и расширенные процедуры см. в мигрированном runbook-контуре AngaraBook.
Goal
Зафиксировать проверяемый workflow:
- что гарантирует backup;
- как выполняется restore;
- какие артефакты подтверждают корректность.
Contract (cold/offline)
- Backup выполняется при остановленном сервере.
- В backup включаются:
storage.data_directory(включая.adb);storage.transaction_log_directory;storage.undo_directory(если вынесен отдельно), либо.audизdata_directory.- Снимок консистентен на момент остановки.
- Для TDE backup восстановление требует валидный key material (fail-closed).
What is out of scope
- Нет hot backup в этом контракте.
- Нет PITR.
- Нет incremental backup.
Pinned commands
CLI (operator-facing, preferred for packaged distribution):
angara-cli backup full --config /etc/angarabase/angarabase.conf --out /tmp/base_full.abk
angara-cli backup verify --file /tmp/base_full.abk --json
Restore via CLI:
angara-cli backup restore \
--config /etc/angarabase/angarabase.conf \
--file /tmp/base_full.abk \
--target-dir /tmp/angarabase-restore \
--overwrite
Legacy tools entrypoint (workspace/dev path):
tools/backup_restore/run.sh backup \
--data-dir /var/lib/angarabase/data \
--txlog-dir /var/lib/angarabase/transaction_log \
--out /tmp/angarabase-backup.tar.gz \
--root artifacts/backup_restore/backup
tools/backup_restore/run.sh restore \
--archive /tmp/angarabase-backup.tar.gz \
--dest /tmp/angarabase-restore \
--force \
--root artifacts/backup_restore/restore
Restore oracle (txlog-level):
tools/backup_restore/oracle.sh --root artifacts/backup_restore_oracle/run_1
Evidence surfaces
Минимум для triage:
summary.json(top-level outcome);backup_manifest.json(inspect);verify_report.json(verify);- oracle JSON (
txlog scan/replay-pages,compare.json).
Upgrade linkage
Перед upgrade версии рекомендуется:
- сделать cold backup;
- сохранить архив как rollback point;
- прогнать restore oracle на отдельной директории.
Совместимость и on-disk policy: src/operations/upgrade-and-migration.md.
Remote Admin Flow (updated 2026-04-23 for TD-2026-0012)
Для packaged distribution (apt install angarabase-server) предпочтителен angara-cli (remote admin over TCP
or local). Legacy tools/backup_restore/run.sh остаётся только для dev/workspace.
Remote admin flow:
angara-cli backup ... --remote-admin(или через configured admin endpoint).- Runbooks в
angarabook/src/operations/теперь ссылаются на packaged CLI вместо прямого вызова tools/. - Evidence:
tools/ci/backup_smoke.sh+ golden_db restore oracle.
last_reviewed: 2026-04-23. Drift resolved.
Config Schema
Операторская сводка по поверхности конфигурации AngaraBase.
Каноничный источник: этот runbook в angarabook/src/operations/.
Goal
Зафиксировать контракт конфига:
- ключи и секции;
- дефолты;
- precedence и совместимость.
Core sections
[server]:addr(основной bind endpoint),host/portкак deprecated.[storage]:data_directory,transaction_log_directory(wal_directoryкак alias),io_backend_strict.[logging]:log_level,log_directory.[transaction_log]:backend,durability,fsync,checkpoint_target_lsn_lag_mb,checkpoint_min_interval_s.[ops]:metrics_addr,admin_addr.[security]:allow_insecure,dev_mode, TDE metadata fields.[memory]:soft_limit_mb,hard_limit_mb,max_dataset_bytes.[wal]:max_size_mb, performance and observability knobs.[execution],[aqp],[diagnostics],[optimizer]: performance and observability knobs.
Config Strictness and Unknown Keys (RM-0.6.5.6)
Начиная с RM-0.6.5.6, наличие неизвестных ключей в именованных секциях ([server], [storage], [wal] и др.) приводит к FATAL ERROR при старте сервера. Это предотвращает опечатки в конфигурации, которые раньше могли игнорироваться.
- При ошибке сервер выводит подсказку (Levenshtein suggestion) для наиболее похожего существующего ключа.
Пример ошибки при опечатке в ключе:
[ERROR] config: unknown key 'max_siz_mb' in section [wal]; did you mean 'max_size_mb'?
Диагностика: если сервер не стартует — проверить stderr / wrapper.log:
grep -i "unknown key\|config:" artifacts/golden_db/logs/wrapper.log | tail -20
WAL and Checkpoint Tuning (RM-0.6.5.8)
-
[wal] max_size_mb: Максимальный размер сегментов WAL. Применяется с RM-0.6.5.6 (ранее игнорировался).- Default: 512
- ENV:
ANGARABASE_WAL_MAX_SIZE_MB - Startup log:
wal: max_size_mb=2048 MiB (source=config)
-
[transaction_log] checkpoint_target_lsn_lag_mb: Целевое отставание LSN для триггера чекпоинта.- Default: 256
- ENV:
ANGARABASE_CHECKPOINT_LSN_LAG_TRIGGER_MB - Startup log:
checkpoint: lsn_lag_trigger_mb=256
-
[transaction_log] checkpoint_min_interval_s: Минимальный интервал между чекпоинтами в секундах.- Default: 300
- ENV:
ANGARABASE_CHECKPOINT_INTERVAL_MS(задается в миллисекундах для ENV)
-
[storage] io_backend_strict(default: false): Строгий режим проверки I/O бэкенда. -
ANGARABASE_CHECKPOINT_BACKGROUND=true: Фоновый чекпоинт теперь включен по умолчанию.
Проверка применения max_size_mb при старте:
grep "wal: max_size_mb" artifacts/golden_db/logs/wrapper.log | tail -3
# Ожидаемый вывод: [INFO] wal: max_size_mb=512 MiB (source=config)
Memory Limits (RM-0.6.5.8)
Секция [memory] управляет потреблением оперативной памяти процессом сервера.
-
soft_limit_mb: Порог RSS (Resident Set Size) в MiB, при котором сервер начинает выдавать предупреждения (warn threshold).- Default: disabled (если не задан)
- Поведение: при пересечении лимита инкрементируется метрика
angarabase_memory_soft_limit_exceeded_total. - Пример:
soft_limit_mb = 4096
-
hard_limit_mb: Жесткий предел RSS в MiB.- Default: disabled (если не задан)
- Поведение: при превышении лимита сервер выполняет экстренный сброс данных (emergency flush) и завершается с
exit(1). - Пример:
hard_limit_mb = 8192
Index Maintenance and Durability (RM-0.6.5.8)
-
Index Durability: Начиная с RM-0.6.5.8, операция
CREATE INDEXгарантирует долговечность (durability). После завершения команды индекс полностью синхронизирован и доступен после восстановления (recovery) даже в случае сбоя сразу после создания. -
storage.max_index_pages_per_table(default: 65535): лимит страниц на один индекс. -
storage.index_maintenance_budget_ms(default: 5000): бюджет времени на поддержку индексов в одной DML команде. -
visibility_map.rebuild_max_pages_per_tick(default: 1024): темп фонового восстановления VM. -
visibility_map.rebuild_io_budget_bytes(default: 10MB): I/O бюджет воркера VM.
Init behavior (--init)
angarabase-server --init использует effective settings и формирует bootstrap layout:
<root>/data<root>/txlog<root>/angarabase.conf(если не задан существующий config path)
Precedence
Правило приоритета:
- default
- config (
angarabase.conf) - environment override
Контракт: default -> config -> env.
Critical env surface (operator minimum)
ANGARABASE_TRANSACTION_LOG*(backend/durability/fsync)ANGARABASE_METRICS_ADDRANGARABASE_TDE_*ANGARABASE_TLS_*ANGARABASE_MAX_DATASET_BYTESANGARABASE_AQP_*ANGARABASE_GC_*
Backward compatibility policy
Breaking считается:
- переименование ключа без alias периода;
- unsafe изменение дефолта (например bind наружу);
- смена семантики без migration notes.
Не-breaking:
- новые ключи с безопасными дефолтами;
- новые fail-closed проверки unsafe комбинаций с явным override.
Spill / Temp Storage (RM-0.6.4.2 — Spill to Disk)
Новые ENV knobs для управления spill-to-disk (Grace Hash Join, External Merge Sort, Set Ops) при превышении QueryMemoryBudget. Default disabled (безопасный fail-closed на OOM 53100).
Core spill knobs:
ANGARABASE_QUERY_SPILL_ENABLED=0— включить spill path (set=1 for analytical workloads).ANGARABASE_TEMP_MAX_BYTES_PER_QUERY(unlimited) — per-query soft quota.ANGARABASE_TEMP_MAX_BYTES_TOTAL_*(SOFT/HARD) — global spill limits, fail-closed on hard.ANGARABASE_TEMP_DIRECT_IO=0,ANGARABASE_TEMP_USE_O_TMPFILE=0,ANGARABASE_TEMP_OTMPFILE_DIRECT_FALLBACK=0— io_uring + O_DIRECT + O_TMPFILE profile (production-like, kernel-managed cleanup on crash).ANGARABASE_SPILL_HASH_JOIN_*(MAX_PARTITION_ROWS=8192, MAX_RECURSION_DEPTH=3, SKEW_THRESHOLD=75%, BLOOM_BITS=65536) — tuning recursion, skew handling, prefilter. Overflow → SQLSTATE 53400 graceful refusal.
Monitoring: see observability-metrics.md for angarabase_spill_*, angarabase_wal_* counters and
sys.wait_events.
See RM-0.6.4.2 Surface Map and RFC-2026-492 for full contract. Recommended for HTAP/TPC-H with low
ANGARABASE_QUERY_MEMORY_LIMIT_MB.
Дальше
- Operations overview — где config-schema встроен в общий operator-материал.
- Operational policies baseline — какие конфигурационные значения зафиксированы политикой.
GC Tuning (RM-0.6.6.11)
Columnar Manifest GC
ANGARABASE_COLUMNAR_MANIFEST_GC_INTERVAL_MS(config key:columnar.manifest_gc_interval_ms): Интервал между запусками фонового ManifestGC worker, который удаляет «ghost» ссылки на сегменты, отсутствующие в BlobStore.- Default:
60000(60 секунд) - Рекомендуемый диапазон: 10000–300000
- Мониторинг:
angarabase_columnar_manifest_gc_removed_total— количество убранных ghost-ссылок;angarabase_catalog_snapshot_segments_total— текущий размер snapshot (индикатор роста манифеста). - Когда уменьшать: если
angarabase_catalog_snapshot_segments_totalстабильно растёт при неизменной нагрузке, аrate(angarabase_columnar_manifest_gc_removed_total[5m])близко к нулю — GC не успевает; уменьши интервал.
- Default:
Index GC Sweep Limit
ANGARABASE_INDEX_GC_MAX_SWEEP_PAGES(config key:storage.index_gc_max_sweep_pages): Максимальное число страниц B-tree, просматриваемых за один sweep IndexGC worker. Ограничивает I/O нагрузку GC на горячих индексах.- Default:
3000 - Рекомендуемый диапазон: 500–10000
- State-based trigger: если
angarabase_index_gc_dead_fraction > 0.15, worker автоматически выполняет внеплановый sweep независимо от таймера. - Мониторинг:
angarabase_index_gc_dead_fraction— текущая доля мёртвых записей (gauge, 0–1). Значение выше 0.20 требует attention.
- Default:
Buffer Pool Config (RM-0.6.6.8)
В RM-0.6.6.8 были добавлены настройки для управления политикой вытеснения страниц и изоляции ресурсов для GC.
ANGARABASE_BUFFER_POOL_EVICTION: Выбор алгоритма вытеснения страниц.- Default:
"2q" - Values:
"2q","3q"(включает полную политику 3Q с разделением на A1/Am очереди).
- Default:
ANGARABASE_BUFFER_POOL_GC_RING_SIZE: Размер кольцевого буфера для операций GC (в страницах).- Default: 256
- Описание: Позволяет изолировать I/O нагрузку от фоновой очистки индексов, предотвращая вымывание полезных данных из основного кэша.
Observability Metrics Reference
Полный справочник метрик AngaraBase с диагностическими маршрутами и quick reference card.
Каноничный источник: этот runbook в angarabook/src/operations/.
Quick Reference Card (Top-10 для wallboard)
Распечатайте и повесьте у дежурного. Эти 10 метрик закрывают 80% production incidents.
| # | Метрика | Тип | Нормальный диапазон | Что значит выход за границу |
|---|---|---|---|---|
| 1 | angarabase_connections_active | gauge | < 80% max_pool | Connection leak / отсутствие PgBouncer — проверить angara_stat_activity |
| 2 | angarabase_txn_rollback_total (rate 1m) | counter rate | < 5% от commit rate | Аномальный rollback rate — конфликты MVCC, deadlock или баги приложения |
| 3 | angarabase_storage_dirty_pages_total | gauge | < 10 000 стр. | Checkpoint не успевает — снизить write rate или уменьшить checkpoint interval |
| 4 | angarabase_checkpoint_errors_total (change) | counter | 0 | Ошибка checkpoint = критичный инцидент; смотреть логи немедленно |
| 5 | angarabase_transaction_log_flush_lsn vs durable_lsn (delta) | gauge | < 1 МБ | Большой gap = WAL durability lag; риск потери данных при crash |
| 6 | angarabase_query_exec_duration_ms_bucket P99 | histogram | < 100 ms | P99 деградация — смотреть angara_stat_activity + EXPLAIN |
| 7 | angarabase_buffer_pool_miss_total (rate) | counter rate | < 20% hit/miss | Низкий cache hit ratio — увеличить buffer_pool_size_mb |
| 8 | angarabase_memory_rss_bytes | gauge | < soft_limit*0.9 | Приближение к soft limit — OOM risk; проверить query patterns + GC |
| 9 | angarabase_qos_rejected_critical_total (rate) | counter rate | 0 | Любые CRITICAL rejections = production incident candidate |
| 10 | angarabase_uptime_seconds | gauge | монотонно растёт | Значение < 60 после паузы = unexpected restart / crash |
Полный справочник метрик
Соединения и сессии
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_connections_active | gauge | Активные клиентские соединения | < max_pool * 0.8 | Проверить pool config, connection leaks |
angarabase_connections_accepted_total | counter | Всего соединений с момента старта | монотонно | Внезапный всплеск rate — DDoS или reconnect storm |
angarabase_pgwire_active_tasks | gauge | Активные spawn_blocking задачи pgwire | ≤ max_blocking_threads | Saturation blocking runtime path |
angarabase_session_claims_set_total | counter | Установки session claims (app.*) | — | Используется для audit trail |
Диагностика соединений:
SELECT pid, state, consumer_id, wait_event FROM angara_stat_activity;
Транзакции и MVCC
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_txn_begin_total | counter | Всего BEGIN | — | Baseline для throughput |
angarabase_txn_commit_total | counter | Всего COMMIT | — | rate(1m) = TPS |
angarabase_txn_rollback_total | counter | Всего ROLLBACK | < 5% от commit | Конфликты, ошибки приложения |
angarabase_txn_active_count | gauge | Транзакций в полёте | < 100 (OLTP) | Долгие txn — проверить txn_oldest_snapshot_age_seconds |
angarabase_txn_commit_conflicts_total | counter | Конфликты MVCC | близко к 0 | Высокий rate = конкурирующие writes на одни строки |
angarabase_txn_oldest_snapshot_age_seconds | gauge | Возраст старейшего snapshot | < 60s | Долгий snapshot блокирует GC → GC bloat |
angarabase_mvcc_history_versions_total | gauge | Версий в MVCC store | растёт медленно | Быстрый рост = GC не успевает (см. MVCC GC runbook) |
angarabase_txn_commit_epoch_current | gauge | Текущая commit epoch | монотонно | Не меняется > 30s при нагрузке = проблема WAL |
PromQL — TPS:
rate(angarabase_txn_commit_total[1m])
PromQL — Conflict ratio:
rate(angarabase_txn_commit_conflicts_total[5m]) / rate(angarabase_txn_commit_total[5m])
WAL и durability
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_transaction_log_flush_lsn | gauge | LSN последней flush | монотонно | Остановка роста = WAL writer hung |
angarabase_transaction_log_durable_lsn | gauge | LSN последнего fsync (глобально) | ≤ flush_lsn | gap > 1 МБ = durability lag |
angarabase_wal_durable_lsn{db="<name>"} | gauge | Per-DB durable LSN после последнего успешного per-DB checkpoint | монотонно растёт под нагрузкой | Остановка роста при активных write в эту БД = checkpoint этой БД не продвигается. Scope: только пользовательские БД (CREATE DATABASE); дефолтная base и системный WAL используют main txlog и здесь НЕ отражены — их durability смотрите по глобальному angarabase_transaction_log_durable_lsn. Серия для БД появляется только после первого успешного per-DB checkpoint этой БД; её отсутствие до этого момента — норма (checkpoint ещё не было), а не сбой. |
angarabase_transaction_log_last_checkpoint_id | gauge | ID последнего checkpoint | монотонно | — |
angarabase_transaction_log_checkpoint_end_valid_total | counter | Успешных checkpoint ends | монотонно | — |
angarabase_transaction_log_checkpoint_end_invalid_total | counter | Невалидных checkpoint ends | 0 | > 0 = повреждение WAL |
angarabase_wal_sync_wait_total | counter | WAL sync waits (strict mode) | — | rate растёт = I/O latency |
angarabase_wal_group_commit_wait_total | counter | WAL group commit waits | — | rate растёт = group commit backlog |
angarabase_transaction_log_bytes_appended_total | counter | Байт записано в WAL | — | WAL write throughput |
angarabase_wal_redo_heap_rows_reconstructed_total | counter | Строки, восстановленные из WAL redo в HeapStore | 0 (steady) | > 0 только при recovery после crash |
angarabase_wal_redo_heap_pages_written_total | counter | Страницы HeapStore, записанные WAL redo pass | 0 (steady) | > 0 только при recovery после crash |
PromQL — WAL durability gap (байт):
angarabase_transaction_log_flush_lsn - angarabase_transaction_log_durable_lsn
PromQL — per-DB durable LSN (прогресс checkpoint по БД, RM-0.6.7.12):
# durable LSN конкретной пользовательской БД
angarabase_wal_durable_lsn{db="orders"}
# БД, чей durable_lsn не двигался 5 мин (checkpoint stall):
# ВНИМАНИЕ: метрика обновляется только на per-DB checkpoint, поэтому для
# idle-БД (без write) значение тоже не меняется — это НЕ stall. Сопоставляйте
# с активностью записи (напр. с ростом angarabase_transaction_log_bytes_appended_total).
changes(angarabase_wal_durable_lsn[5m]) == 0
PromQL — восстановление строк при последнем старте (S2):
# Instant value показывает итог последнего recovery pass
angarabase_wal_redo_heap_rows_reconstructed_total
Note: Метрики
angarabase_wal_redo_heap_*инкрементируются только во время WAL redo pass при старте после некорректного завершения (SIGKILL/crash). В стабильном состоянии (steady state) их значения не меняются.
Storage и buffer pool
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_storage_dirty_pages_total | gauge | Грязные страницы в памяти | < 10 000 | Checkpoint lag; снизить write rate или checkpoint_interval |
angarabase_storage_cached_pages_total | gauge | Закэшированные страницы | растёт до bp size | Внезапное падение = eviction storm |
angarabase_buffer_pool_hit_total | counter | Cache hits | — | hit rate = hits / (hits + misses) |
angarabase_buffer_pool_miss_total | counter | Cache misses | — | miss rate > 20% = нужен больший buffer pool |
angarabase_buffer_pool_warmup_pages_total | counter | Страниц загружено при warmup | — | После restart |
angarabase_storage_flush_ok_total | counter | Успешных flush | монотонно | — |
angarabase_storage_backpressure_events_total | counter | Backpressure events | 0 | > 0 = writer faster than disk |
angarabase_storage_backpressure_commit_rejected_total | counter | Commit rejected by backpressure | 0 | Производительность I/O недостаточна |
angarabase_storage_flush_bytes_total | counter | Байт сброшено на диск | — | I/O write throughput |
PromQL — Buffer pool hit ratio:
rate(angarabase_buffer_pool_hit_total[5m]) /
(rate(angarabase_buffer_pool_hit_total[5m]) + rate(angarabase_buffer_pool_miss_total[5m]))
Checkpoint и bgwriter
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_checkpoint_total | counter | Успешных чекпоинтов | > 0 за 5 мин | = 0 за 10 мин = checkpoint stopped |
angarabase_checkpoint_errors_total | counter | Ошибок checkpoint | 0 | Немедленно смотреть логи |
angarabase_checkpoint_dirty_pages | gauge | Грязных страниц на момент checkpoint | < 5 000 | Высокое значение = checkpoint не успевает |
angarabase_checkpoint_duration_ms_sum | counter | Суммарное время checkpoint (мс) | — | avg = sum/count |
angarabase_checkpoint_aborted_total | counter | Прерванных checkpoint | 0 | > 0 = отмены; проверить причину |
angarabase_checkpoint_per_db_timeout_total | counter | Per-DB checkpoint timeouts | 0 | timeout = диск слишком медленный |
angarabase_wal_forced_checkpoints_total | counter | Принудительных checkpoint по backpressure | 0 | > 0 = write pressure критична |
angarabase_overlay_flush_on_checkpoint_slots_total | counter | Overlay-слоты, сброшенные в heap при checkpoint | — | Интенсивность материализации overlay |
angarabase_overlay_flush_on_checkpoint_tables_total | counter | Таблицы, затронутые overlay flush | — | — |
SQL — состояние bgwriter:
SELECT * FROM angara_stat_bgwriter;
PromQL — checkpoint avg duration:
rate(angarabase_checkpoint_duration_ms_sum[5m]) / rate(angarabase_checkpoint_duration_ms_count[5m])
PromQL — интенсивность материализации overlay (S1):
# Индикатор давления на HeapStore со стороны overlay-слоев
rate(angarabase_overlay_flush_on_checkpoint_slots_total[5m])
Query execution
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_query_exec_total_ok_select | counter | SELECT queries OK | — | QPS baseline |
angarabase_query_exec_total_ok_write | counter | Write queries OK | — | Write TPS |
angarabase_query_exec_total_err_select | counter | SELECT errors | близко к 0 | rate растёт = баги или перегрузка |
angarabase_query_exec_duration_ms_bucket | histogram | Latency distribution | P99 < 100ms | P99 > 500ms = деградация |
angarabase_slow_query_total | counter | Slow queries (> threshold) | 0 | > 0 = нужен EXPLAIN slow queries |
angarabase_sql_routing_not_supported_total | counter | Unsupported SQL routes | 0 | > 0 = приложение использует неподдерживаемый SQL |
angarabase_legacy_fallback_triggered_total | counter | Legacy path fallbacks | 0 | > 0 = unsupported query план |
angarabase_simd_agg_fallback_total | counter | Fallback SIMD агрегации на скалярный путь | 0 | > 0 = отсутствие поддержки AVX2/NEON или несовместимость типов |
angarabase_adaptive_probe_swap_total | counter | Количество адаптивных переключений сторон Hash Join | — | Показывает активность оптимизатора при перекосе размеров таблиц |
PromQL — P99 latency:
histogram_quantile(0.99,
rate(angarabase_query_exec_duration_ms_bucket[5m])
)
SQL — медленные запросы:
SELECT query, calls, mean_exec_time_ms, max_exec_time_ms
FROM angara_stat_statements
ORDER BY mean_exec_time_ms DESC LIMIT 10;
Memory
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_memory_rss_bytes | gauge | RSS процесса (байт) | < soft_limit * 0.9 | OOM risk; проверить query patterns |
angarabase_memory_soft_limit_exceeded_total | counter | Превышений soft_limit_mb | 0 | > 0 = память под давлением |
angarabase_tx_overlay_dataset_bytes_total | gauge | In-memory tx overlay size | < 512 МБ | Большие txn держат много данных в памяти |
QoS Scheduler
| Метрика | Тип | Что измеряет | Норма | Выход за границу |
|---|---|---|---|---|
angarabase_qos_rejected_critical_total | counter | Отказов CRITICAL queue | 0 | Incident candidate — немедленный triage |
angarabase_qos_rejected_interactive_total | counter | Отказов INTERACTIVE queue | 0 | User-facing degradation |
angarabase_qos_rejected_background_total | counter | Отказов BACKGROUND queue | — | Снизить background concurrency |
angarabase_qos_blocking_inflight | gauge | Блокирующих задач | < max_blocking | scheduler saturation |
angarabase_spawn_blocking_active | gauge | Активных spawn_blocking | < max_blocking | — |
Troubleshooting by Dashboard
Маршрут 1: Высокий P99 latency
angarabase_query_exec_duration_ms P99 > 500ms?
│
├─ Да → angara_stat_activity: есть waiting sessions?
│ │
│ ├─ Да (wait_event != '') → Lock contention или WAL sync wait
│ │ → смотреть angarabase_txn_commit_conflicts_total
│ │ → смотреть angarabase_wal_sync_wait_total
│ │
│ └─ Нет → angara_stat_statements: top queries by max_exec_time_ms
│ → EXPLAIN на топ-запрос
│ → проверить buffer_pool_miss_total rate (I/O bound?)
│
└─ Нет → baseline нормальный, false alarm
SQL:
SELECT query, calls, max_exec_time_ms, mean_exec_time_ms
FROM angara_stat_statements
ORDER BY max_exec_time_ms DESC LIMIT 5;
Маршрут 2: QPS Drop (внезапное падение SELECT rate)
rate(angarabase_query_exec_total_ok_select[1m]) резко упал?
│
├─ connections_active тоже упал → процесс restarted? uptime < 60s?
│ → смотреть логи на panic / OOM / segfault
│
├─ connections_active высокий, QPS низкий → scheduler saturation?
│ → qos_rejected_* > 0?
│ → qos_blocking_inflight высокий?
│ → spawn_blocking_active ≈ spawn_blocking_max?
│
└─ Connections нормальные → долгая транзакция блокирует?
→ angara_stat_activity WHERE state = 'idle in transaction'
→ txn_oldest_snapshot_age_seconds > 60s?
Маршрут 3: GC Pressure / MVCC bloat
mvcc_history_versions_total монотонно растёт без снижения?
│
├─ txn_oldest_snapshot_age_seconds > 120s → долгий открытый snapshot
│ → найти pid из angara_stat_activity ORDER BY query_start ASC
│ → завершить или дождаться завершения
│
├─ columnar_pending_deleted_rows > 1M → compaction lagging
│ → проверить Background Compactor в angara_stat_activity
│ → временно SET angarabase.compaction_enabled = true
│
└─ memory_rss_bytes растёт вместе → GC bloat + memory pressure
→ смотреть mvcc-gc.md runbook
Маршрут 4: Checkpoint Issues
checkpoint_errors_total изменился?
│
├─ Да → немедленно смотреть логи (disk full? I/O error?)
│ → storage_backpressure_events_total > 0?
│ → df -h на data directory
│
└─ Нет, но dirty_pages_total высокий (> 10 000)?
→ checkpoint не поспевает за writes
→ снизить checkpoint_interval_ms
→ или ограничить write throughput
→ SQL: SELECT * FROM angara_stat_bgwriter;
Memory and Buffer Pool Metrics (RM-0.6.5.8)
Goal
Держать минимально достаточный набор сигналов для:
- durability;
- concurrency/locks;
- storage/checkpoint;
- recovery.
Metrics source
ANGARABASE_METRICS_ADDR=host:port- endpoint:
GET /metrics(Prometheus format)
Must-have groups
- Transactions / concurrency
- Transaction log / durability
- Locks
- Storage / writeback / checkpoint
- Query diagnostics / stats
- Recovery / replay outcomes
Memory and Buffer Pool Metrics (RM-0.6.5.8)
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_memory_rss_bytes | gauge | Resident Set Size процесса сервера в байтах. Обновляется каждые 5с. |
angarabase_memory_soft_limit_exceeded_total | counter | Количество пересечений порога soft_limit_mb (edge-trigger). |
angarabase_buffer_pool_warmup_evictions_during_warmup_total | counter | Количество вытеснений страниц из buffer pool во время прогрева (warmup cap enforcement). |
angarabase_buffer_pool_warmup_completed_pages | counter | Количество страниц, загруженных при прогреве. |
angarabase_buffer_pool_warmup_aborted_at_cap_total | counter | Warmup прерван из-за превышения cap (>95%). |
PromQL — Алерт при приближении к soft limit:
# Замените <soft_limit_bytes> на значение soft_limit_mb * 1024 * 1024
# Например, для soft_limit_mb = 4096: порог = 4294967296
angarabase_memory_rss_bytes > <soft_limit_bytes> * 0.9
Storage and Checkpoint Metrics (RM-0.6.5.8)
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_checkpoint_total | counter | Общее число выполненных чекпоинтов. > 0 после 5 мин uptime подтверждает работу auto-checkpoint. |
Visibility Map and Index-Only Scan (RM-0.6.4.3)
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_visibility_map_all_visible_fraction | gauge | Доля all-visible страниц (сигнал для планировщика). |
angarabase_index_only_scan_hits_total | counter | Успешные Index-Only Scan (без обращения к Heap). |
angarabase_index_only_scan_heap_fetches_total | counter | Fallback на Heap при Index-Only Scan (бит VM=0). |
angarabase_visibility_map_rebuild_pages_remaining | gauge | Остаток страниц для фонового восстановления VM. |
angarabase_visibility_map_corrupt_total | counter | Обнаруженные повреждения VM (триггер rebuild). |
Конкретные имена метрик с привязкой к dashboard-панелям: см. таблицу Полный contract имён фиксируется тестом, ссылка ниже в «Contract pinning».
Новые метрики RM-0.6.4.0 (WAL Commit-Path + Durability)
Добавлены в Sprint 2/3 RM-0.6.4.0 (RFC-2026-090). Покрывают новый режим sync_at_commit
и группу durability barrier.
curl -sf http://127.0.0.1:9898/metrics | rg "wal_(sync_wait|group_commit_wait)|wait_events_total\\{event=\"wal_"
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_wal_sync_wait_total | counter | Число commit-wait событий по пути IO::WalSync (строгая durability). |
angarabase_wal_group_commit_wait_total | counter | Число commit-wait событий по пути IO::WalGroupCommit (батчевый durability wait). |
angarabase_wait_events_total{event="wal_sync"} | counter | Унифицированный wait-event счётчик по WAL sync пути. |
angarabase_wait_events_total{event="wal_group_commit"} | counter | Унифицированный wait-event счётчик по group-commit пути. |
Диагностика по режиму
relaxed:wal_sync_wait_totalиwal_group_commit_wait_totalблизки к 0.group_commit: растётwal_group_commit_wait_total;wal_sync_wait_totalобычно заметно ниже.sync_at_commit/strict: растётwal_sync_wait_total;wait_events_total{event="wal_sync"}отражает долговременную нагрузку sync-path.
Режим durability проверяется через env ANGARABASE_TRANSACTION_LOG_DURABILITY.
SQL SET durability / COMMIT WITH DURABILITY зарезервированы для v0.6.5 → SQLSTATE 0A000.
Подробнее: WAL writer contract spec (wal_writer_contract_v0.md) и RFC-2026-090.
HTAP / Vector Execution Metrics (RM-0.6.4.13 / RM-0.6.4.14 / RM-0.6.6.9)
HTAP-специфичные метрики для диагностики векторного и stream-пути выполнения.
Контракт меток стабильный начиная с v0.6.x.
curl -sf http://127.0.0.1:9898/metrics | grep -E "scan_stream|vector_fallback|vector_memory|columnar_manifest|vector_columnar_native|columnar_batched_scan|segments_pruned|parallel_agg|vector_numeric_float_backed|vector_columnar_grouped_agg"
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_scan_stream_materialize_total{reason="batch_to_rows"} | counter | Материализация на границе batch→rows. |
angarabase_scan_stream_materialize_total{reason="drain_rows_default"} | counter | Материализация через drain_rows (fallback default). |
angarabase_scan_stream_materialize_total{reason="stream_to_relation_boundary"} | counter | Материализация на границе stream→relation. |
angarabase_scan_stream_fallback_total | counter | Fallback stream-плана на legacy executor. |
angarabase_vector_fallback_total | counter | Fallback vector-пути на row-путь (неподдерживаемый план или ошибка типа). |
angarabase_vector_columnar_native_total | counter | Успешные активации нативного векторного пути для columnar таблиц. |
angarabase_columnar_batched_scan_batches_total | counter | Всего обработанных колоночных батчей в нативном пути. |
angarabase_columnar_segments_pruned_total | counter | Количество сегментов, отсеченных по метаданным (zone-map pruning). |
angarabase_parallel_agg_total | counter | Количество запусков параллельного агрегатора. |
angarabase_vector_memory_budget_exceeded_total | counter | Отказ выделения бюджета вектора (SQLSTATE 53100). |
angarabase_columnar_manifest_init_failed_total | counter | Ошибка init SegmentManifest при CREATE TABLE USING COLUMNAR. |
angarabase_vector_numeric_float_backed_total | counter | Lossy-mapping: numeric(p,s>0) → Float64 в vector-пути (RM-0.6.7.15). Ненулевое = float-потеря точности. Подробнее: vector-numeric-columnar-agg-metrics.md. |
angarabase_vector_columnar_grouped_agg_total | counter | GROUP BY выполнен колоночным hash-agg путём (не row-fallback). Path-signal (RM-0.6.7.15). |
Примечание: метки
reason=уangarabase_scan_stream_materialize_total— стабильный оператор-facing контракт в рамкахv0.6.x.
Columnar DV Pressure (RM-0.6.4.19 Track C C2)
angarabase_columnar_pending_deleted_rows — signed gauge, показывающий суммарное
количество логически удалённых строк в живых сегментах, ещё не reclaimed compaction.
- Increment при
AttachDeleteVector(при каждом columnar DELETE):+row_countиз DV op. - Decrement при
compact_l0_to_l1:-rows_reclaimedпо числу строк, не вошедших в L1 pack.
В норме gauge растёт после DELETE и снижается после Background Compactor runа. Если gauge монотонно растёт — compaction lagging или compaction полностью отключён.
curl -sf http://127.0.0.1:9898/metrics | rg "pending_deleted_rows"
Alert правило (DV fragmentation)
# Alert если накопленный DV pressure > 5 млн строк.
angarabase_columnar_pending_deleted_rows > 5_000_000
Рекомендуемые severity:
warningпри превышении >1M строк — compaction, вероятно, отстаёт;criticalпри превышении >10M строк — возможна деградация scan performance.
Интерпретация:
- gauge ≤ 0 — нормально (все DV reclaimed, возможно небольшой transient underflow при replay);
- gauge растёт без уменьшения > 30 минут — проверьте Background Compactor (
angara_stat_activity,angarabase_columnar_compaction_total).
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_columnar_pending_deleted_rows | gauge (signed) | Net pending-deleted rows по всем columnar сегментам. |
Heap fetch fallback reason metrics (RM-0.6.5.6)
angarabase_heap_point_fetch_fallback_reason_stale_tid_index_total— fallback из-за stale tid indexangarabase_heap_point_fetch_fallback_reason_not_found_total— fallback из-за row not found
Быстрая проверка (curl):
curl -s http://localhost:8080/metrics | grep "fallback_reason"
# angarabase_heap_point_fetch_fallback_reason_stale_tid_index_total 0
# angarabase_heap_point_fetch_fallback_reason_not_found_total 0
PromQL — rate fallback по причинам:
rate(angarabase_heap_point_fetch_fallback_reason_stale_tid_index_total[5m])
rate(angarabase_heap_point_fetch_fallback_reason_not_found_total[5m])
Если stale_tid_index растёт — возможна проблема с V3 chain path или index rebuild. Если not_found растёт — возможна потеря данных или баг в MVCC visibility.
QoS Scheduler и spawn_blocking (RM-0.6.4.10 / RM-0.6.4.19)
RM-0.6.4.10 добавляет runtime-сигналы для QoS scheduler и blocking path. Они
помогают отличать SQL contention от scheduler saturation: если растут QoS
rejections или qos_blocking, проблема находится в очередях выполнения, а не в
row/table locks.
curl -sf http://127.0.0.1:9898/metrics | rg "qos_(queued|rejected|blocking)|spawn_blocking"
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_qos_queued_critical_total | counter | Всего задач поставлено в QoS CRITICAL queue. |
angarabase_qos_queued_interactive_total | counter | Всего задач поставлено в QoS INTERACTIVE queue. |
angarabase_qos_queued_background_total | counter | Всего задач поставлено в QoS BACKGROUND queue. |
angarabase_qos_rejected_critical_total | counter | Отказы CRITICAL queue с SQLSTATE 53600. |
angarabase_qos_rejected_interactive_total | counter | Отказы INTERACTIVE queue с SQLSTATE 53600. |
angarabase_qos_rejected_background_total | counter | Отказы BACKGROUND queue с SQLSTATE 53600. |
angarabase_qos_blocking_inflight | gauge | Текущие blocking tasks across QoS shards. |
angarabase_spawn_blocking_max | gauge | Лимит spawn_blocking threads из настройки max_blocking_threads; 0 до startup init. |
angarabase_spawn_blocking_active | gauge | Активные spawn_blocking задачи. Инкрементируется при запуске, декрементируется при завершении через SpawnBlockingGuard (RM-0.6.4.19 Track C C2). |
Очереди QoS по уровням:
rate({__name__=~"angarabase_qos_queued_.*_total"}[5m])
Отказы QoS по уровням:
rate({__name__=~"angarabase_qos_rejected_.*_total"}[5m])
Alert на любой отказ scheduler:
sum(rate({__name__=~"angarabase_qos_rejected_.*_total"}[5m])) > 0
Blocking pressure:
angarabase_qos_blocking_inflight > 0
Запас blocking budget:
angarabase_spawn_blocking_max - angarabase_spawn_blocking_active
Интерпретация:
- растёт
queued_background_total, но нетrejected_*— scheduler принимает batch workload, обычно это нормальная картина; - растёт
rejected_background_total— batch/ETL слишком агрессивен, снижайте concurrency или повышайтеANGARABASE_QOS_MAX_QUEUED; - растёт
rejected_critical_total— это production incident candidate: CRITICAL workload не должен регулярно упираться в queue cap; qos_blocking_inflight > 0вместе with ростомqos_blockingwait event означает pressure в blocking runtime path.
Query Execution Duration Histogram (RM-0.6.5.10)
angarabase_query_exec_duration_ms — histogram задержки выполнения SQL-запросов.
Note (RM-0.6.5.10 S6):
histogram_quantile(0.99)корректен только если значение < 10 000ms. При p99 ≥ 10 000ms смотреть долю в bucket+Inf. Buckets:[1,5,10,50,100,500,1000,2500,5000,10000,+Inf]ms.
SLO-oriented usage
- Latency:
histogram_quantile()по*_bucket(p95/p99) - Throughput:
rate()по counters - Errors/contention: conflict/timeout/deadlock rates
- Saturation: backpressure counters and queue depth
Contract pinning
Имена must-have метрик считаются частью operability contract и защищаются тестом:
crates/angarabase/src/metrics.rsprometheus_export_contains_must_have_metrics_names
Дальше
- Performance tuning guide — какие метрики читать в первую очередь при деградации.
- Parallel runtime observability runbook — узкоспецифичные метрики параллельного рантайма.
- MVCC and GC operator minimum — отдельный пакет MVCC/GC-метрик и алертов.
Materialized View Metrics
| Metric | Type | Description |
|---|---|---|
angarabase_mv_refresh_total | counter | Total number of materialized view refreshes. Labels: {mode, status}. |
angarabase_mv_refresh_duration_ms | histogram | Duration of materialized view refresh operations. Labels: {mode}. |
angarabase_mv_auto_refresh_scheduled_total | counter | Number of automatically triggered (scheduled) refreshes. |
angarabase_mv_auto_refresh_lag_seconds | gauge | Lag between the scheduled refresh time and actual refresh time. Labels: {mv}. |
angarabase_mv_incremental_refresh_rows_applied_total | counter | Number of rows applied during incremental (async) refreshes. Labels: {mv_name}. |
Online DDL Metrics
| Metric | Type | Description |
|---|---|---|
angarabase_online_ddl_operations_total | counter | Total number of Online DDL operations initiated. Labels: {op, status}. |
angarabase_online_ddl_copy_rows_total | counter | Total number of rows copied during the ghost-table phase. Labels: {table}. |
angarabase_online_ddl_cutover_duration_ms | histogram | Duration of the final cutover phase (blocking). |
Метрики статистики (RM-0.6.7.2)
| Метрика | Тип | Описание |
|---|---|---|
angarabase_stats_inline_updates_total | counter | Число inline-обновлений row_count_live на COMMIT. Ненулевое при активных DML транзакциях. |
angarabase_stats_async_recalc_active | gauge | 1 когда фоновый воркер активно выполняет гистограммный пересчёт, 0 — простой. |
angarabase_stats_drift_ratio | gauge | Коэффициент дрейфа статистики (0–1000, масштабировано). Растёт при большом числе DML без ANALYZE. |
angarabase_optimizer_drift_fallback_total | counter | Число планов где HashJoin был пропущен из-за Snapshot Age Dampening (RFC-2026-196 §4). |
Метрики vector-пути: NUMERIC float-backed и columnar grouped-agg
Две operator-facing counter-метрики, добавленные в RM-0.6.7.15 (vector batch foundation). Обе — кумулятивные counter (Prometheus), сбрасываются только при рестарте процесса.
curl -sf http://127.0.0.1:9898/metrics | grep -E "vector_numeric_float_backed|vector_columnar_grouped_agg"
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_vector_numeric_float_backed_total | counter | Количество раз, когда колонка numeric(p,s>0) / decimal(p,s>0) была спроецирована в физический тип Float64 на vector-пути (lossy). |
angarabase_vector_columnar_grouped_agg_total | counter | Количество раз, когда GROUP BY-агрегат был выполнен колоночным hash-agg путём (а не через row-fallback). Path-signal. |
angarabase_vector_numeric_float_backed_total
Что значит. AngaraBase в v0.6.x не имеет настоящего fixed-point DECIMAL-типа: значения
numeric/decimal хранятся end-to-end как Value::Float(f64) (см. TD-2026-0417, полный Decimal-тип
запланирован на v0.7 + RFC-2026-516). Для numeric с ненулевым scale (numeric(10,2), decimal(18,4)
и т.п.) это означает потенциальную потерю точности в SUM/AVG над денежными колонками
(catastrophic cancellation при суммировании больших и малых величин).
Когда инкрементируется. На каждый вызов вывода физического типа (infer_physical_type) для колонки
типа numeric(p,s) / decimal(p,s) с scale > 0. Параллельно при первом таком событии в процессе
эмитится one-shot WARN в лог (не на каждую строку — флаг через AtomicBool).
Когда НЕ инкрементируется:
numeric/decimalбез суффикса (scale=0 неявно);numeric(10)— указана только precision;numeric(18,0)— явный scale=0 (целочисленный numeric, точен до 2^53).
Важно: счётчик растёт по числу вызовов type-inference, а не по числу строк или запросов. Один запрос с одной numeric(p,s>0)-колонкой может дать несколько инкрементов (per-batch type-inference). Используйте метрику как сигнал наличия lossy-использования, а не как точную меру объёма.
PromQL: алерт на lossy-numeric использование
# Появилось lossy-numeric использование за последний час (раньше не было).
increase(angarabase_vector_numeric_float_backed_total[1h]) > 0
Troubleshooting (DBA)
- Счётчик > 0 → в рабочей нагрузке есть агрегаты над
numeric(p,s>0). Результаты SUM/AVG над такими колонками могут отличаться от точного decimal-результата на величину float-ошибки. - Действие: для денежных колонок, где важна точность до копейки, до выхода v0.7 DECIMAL —
агрегируйте на стороне приложения в целочисленных «минорных единицах» (копейки) или храните как
bigint(scale=0), либо принимайте округление float8 осознанно. - WARN в логе содержит scale и ссылку на TD-2026-0417 — ищите по строке
numeric(... ) column mapped to Float64.
angarabase_vector_columnar_grouped_agg_total
Что значит. Path-signal: GROUP BY-агрегат прошёл оптимизированным колоночным hash-agg путём
(без построчной материализации to_rows() и без string-кодирования ключа группы). Покрывает два места:
- vector-операторный путь (
VectorAggV0— composite key прямо из ColumnData); - columnar SIMD-путь над
HtapRowColumn-таблицами (S3).
Когда инкрементируется. Один раз на завершённый вызов колоночного grouped-agg, когда:
- в плане есть GROUP BY (непустой ключ группы);
- все aggregate-specs поддержаны колоночным путём (COUNT/SUM/MIN/MAX, поддержанные типы ключа);
- (для S3) таблица — columnar-tier (
ENGINE=htap_row_column).
Когда НЕ инкрементируется (запрос ушёл в row-fallback):
- неподдержанный паттерн (DISTINCT, нестандартный/выражение-ключ);
- ungrouped-агрегат (нет GROUP BY) — там путь иной;
- row-store таблица не достигает columnar S3-пути (авто-тиринг = v0.7, RM-0.7.7.1).
Эквивалентность результата колоночного пути row-fallback подтверждена AC-тестами RM-0.6.7.15 (S2-G2 / S3-G3). Метрика — наблюдаемость пути, не корректности.
PromQL: доля columnar-пути vs row-fallback
# Columnar grouped-agg активаций за 5 минут.
increase(angarabase_vector_columnar_grouped_agg_total[5m])
# Доля columnar-пути от всех vector-fallback'ов (грубый индикатор «насколько часто
# GROUP BY уходит в медленный row-fallback»).
increase(angarabase_vector_columnar_grouped_agg_total[5m])
/
clamp_min(
increase(angarabase_vector_columnar_grouped_agg_total[5m])
+ increase(angarabase_vector_fallback_total[5m]),
1
)
Troubleshooting (DBA)
- Счётчик не растёт на HtapRowColumn-таблице при GROUP BY-нагрузке → запрос уходит в row-fallback. Проверьте: нет ли DISTINCT, выражения в ключе группировки, неподдержанной агрегатной функции; всё ли — columnar-eligible specs. Row-fallback корректен, но медленнее.
- Счётчик растёт, а ожидалась SIMD-агрегация — это норма: grouped-agg ходит hash-group путём, а «чистый» SIMD-kernel применяется только для ungrouped COUNT/SUM/MIN/MAX.
- Сопоставляйте с
angarabase_vector_fallback_totalиangarabase_parallel_agg_totalдля полной картины маршрутизации vector-пути.
Связанные метрики
См. раздел HTAP / Vector Execution Metrics общего справочника
(angarabase_vector_fallback_total, angarabase_vector_columnar_native_total,
angarabase_parallel_agg_total).
NUMERIC / DECIMAL — точный фиксированный тип (Phase 0)
RM-0.6.7.16 (RFC-2026-516). Начиная с этого релиза
NUMERIC(p,s)/DECIMAL(p,s)хранятся и считаются точно (128-bit fixed-point черезrust_decimal), а не как приближение поверхdouble. Покрывает деньги/биллинг/ERP до 28 значащих цифр.
Что это даёт оператору
- Точные деньги.
SUM,AVG,+ - * /надNUMERICдают exact-результат, без float-дрейфа:0.10 + 0.20 = 0.30(а не0.30000000000000004). - Хранимый scale значим.
INSERT ... VALUES (12.5)в колонкуNUMERIC(10,2)хранится и выводится как12.50(округление round-half-away-from-zero, как в PostgreSQL). - pgwire. Колонка отдаётся клиенту как PostgreSQL
numeric(OID 1700); текстовый формат значения несёт фиксированный scale.
DDL
CREATE TABLE invoice (
id INT,
amount NUMERIC(18,2), -- точные деньги
rate DECIMAL(10,6) -- синоним NUMERIC
);
Правила typmod:
1 ≤ precision ≤ 28,0 ≤ scale ≤ precision.NUMERIC(18, 2)(пробелы внутри скобок) — допустимо.NUMERICбез typmod — без ограничения precision/scale.
Арифметика и масштаб (scale)
| Операция | scale результата |
|---|---|
a + b, a - b | max(scale_a, scale_b) |
a * b | scale_a + scale_b |
a / b | max(scale_a, 6) |
При записи в колонку значение приводится к её scale округлением round-half-away-from-zero
(-0.5 → -1, 0.5 → 1).
SQLSTATE (что увидит DBA)
| SQLSTATE | Когда |
|---|---|
22003 numeric_value_out_of_range | переполнение (> 96-bit / p>28 диапазона), а также cast NaN/Infinity → numeric |
22012 division_by_zero | деление на ноль |
22P02 invalid_text_representation | 'abc'::numeric (невалидный текст) |
0A000 feature_not_supported | p>28 в DDL; 'NaN'::numeric; индекс по numeric-колонке (см. ниже) |
22023 invalid_parameter_value | невалидный typmod (scale>precision, precision=0) |
Ограничение Phase 0: индексы по NUMERIC
Индекс по NUMERIC/DECIMAL-колонке в Phase 0 не поддержан — CREATE INDEX на такой
колонке возвращает 0A000 feature_not_supported. Диапазонные запросы по numeric идут
seq-scan’ом. Упорядоченный индекс по decimal планируется в v0.7 (TD-2026-0428).
Метрики (Prometheus)
| Метрика | Значение |
|---|---|
angarabase_decimal_overflow_total | переполнения/NaN-Inf cast → 22003 |
angarabase_decimal_legacy_floatread_total | legacy float-backed numeric-значения, прочитанные и нормализованные в Decimal (см. миграцию) |
angarabase_decimal_index_fallback_total | отклонённые fail-closed запросы индекса по numeric (0A000) |
PromQL пример (рост лоссовых чтений старых данных):
rate(angarabase_decimal_legacy_floatread_total[5m])
Миграция существующих NUMERIC-данных
Колонки NUMERIC, созданные до Phase 0, хранили значения как double (float-backed).
После апгрейда они читаются через dual-read: при чтении такое значение нормализуется в
Decimal (счётчик angarabase_decimal_legacy_floatread_total).
⚠️ Важно: dual-read значения наследуют исходную float-неточность — точность гарантируется только для строк, записанных после Phase 0. Колонка со смешанными старыми (float) и новыми (exact) строками считается единообразно как Decimal, но старые значения остаются настолько точными, насколько были во float. Чтобы сделать историю точной — перезапишите её (
UPDATE) после апгрейда.
Вне scope Phase 0 (горизонт v0.7)
- Binary-формат pgwire NUMERIC (NBASE-10000) — сейчас text-wire.
- Индексируемый decimal (order-preserving).
- Arbitrary precision > 28 цифр (varlena).
- Decimal-SIMD в векторном движке — numeric-агрегаты считаются точным row-движком.
Columnar / HTAP Tables
Source of truth: RFC-2026-092, RM-0.6.4.0 Sprint 3.
Что такое HTAP row-column store
AngaraBase поддерживает хранение таблиц в HTAP row-column формате (HtapRowColumn):
строки пишутся через обычный WAL, колонки сегментированы в ColumnStore (SegmentManifest).
Это позволяет обслуживать OLTP транзакции и AP-сканы из одной таблицы.
Векторный конвейер (OLAP)
Для высокопроизводительной аналитики (OLAP) используется Vector Pipeline, который задействует SIMD и параллельную агрегацию напрямую из колоночных данных.
Создание HTAP-таблицы (copy-paste готово)
Есть два эквивалентных синтаксиса:
-- Вариант 1: PostgreSQL-style USING (рекомендуется)
CREATE TABLE metrics (
ts TIMESTAMPTZ NOT NULL,
device_id INT NOT NULL,
value FLOAT8
) USING COLUMNAR;
-- Вариант 2: WITH-опция (явный alias)
CREATE TABLE events (
id SERIAL PRIMARY KEY,
data TEXT
) WITH (storage = 'columnar');
-- Вариант 3: каноническое имя движка
CREATE TABLE events2 (
id SERIAL PRIMARY KEY,
data TEXT
) WITH (storage = 'htap_row_column');
Все три формы эквивалентны: таблица создаётся с TableStorageEngineV0::HtapRowColumn
в catalog.
Проверка engine в catalog
-- Через sys_catalog (RM-0.6.4.0)
SELECT table_name, storage_engine
FROM sys.tables
WHERE table_name = 'metrics';
Фоновая компактизация (L1 Compaction)
Начиная с RM-0.6.4.8, angarabase поддерживает фоновую компактизацию (L1 Compaction) для columnar таблиц.
Компактизатор объединяет мелкие L0 сегменты в крупные L1 pack-файлы, что снижает нагрузку на inodes и улучшает сжатие.
Процесс работает полностью прозрачно.
Метрики для мониторинга компактизации:
angarabase_columnar_compaction_totalangarabase_columnar_compaction_duration_msangarabase_columnar_direct_io_fallback_total
Ошибки и их смысл
Неизвестный USING метод → 0A000
ERROR: USING brin is not a supported storage method; ...
SQLSTATE: 0A000 (feature_not_supported)
Что делать: используйте USING COLUMNAR, USING htap_row_column (→ HTAP),
или опустите USING (→ row_store по умолчанию).
Недопустимое значение storage
ERROR: storage expects one of: row_store, memory, columnar, htap_row_column
SQLSTATE: 42601 (syntax_error)
Что делать: используйте одно из перечисленных значений.
Non-goals (Phase 1, RM-0.6.4.0)
- SegmentManifest auto-init при создании таблицы — deferred to Sprint 4 (OQ-S3-3).
- OOM protection для Column Cache — Sprint 4 (OQ-S3-4).
- Полная AP-оптимизация сканов — RFC-2026-092 Phase 2.
Связанные
- Performance tuning guide — tuning для mixed OLTP+HTAP нагрузок.
- Observability metrics — метрики columnar store.
- RFC-2026-092: HTAP Sync and Materialization v1.
Wait Events
AngaraBase 0.6.3.9 §S11 — базовая модель wait events. RM-0.6.4.10 добавляет QoS scheduler events. RM-0.6.4.19 Track C C1 добавляет per-session счётчики и per-session запрос
angara_stat_wait_events.
Эта страница описывает taxonomy WaitEvent, которую AngaraBase использует для
классификации блокирующих операций. Для оператора wait events отвечают на вопрос:
“на чём кластер сейчас ждёт?” без strace, ручного разбора stack traces и
инструментации каждого call site.
Зачем нужна модель wait events
Модель похожа на pg_stat_activity.wait_event в PostgreSQL или
sys.dm_os_wait_stats в SQL Server:
- каждый блокирующий участок кода получает конкретную причину ожидания;
- текущий wait виден на уровне session/activity;
- агрегированные метрики дают rate, active count и latency distribution по каждому событию;
- dashboards сравнивают разные классы ожиданий через единый label
event=<variant_snake_case>.
Два слоя observability:
- Текущий wait сессии —
angara_stat_activity.wait_event_typeиangara_stat_activity.wait_event. - Агрегированные метрики Prometheus — counters, gauges и histograms по каждому wait event.
События
WaitEvent — стабильный public API. Добавление variant является non-breaking:
dashboards увидят новый event=... label после upgrade. Удаление, renumbering
или изменение as_str() значения считается breaking change.
| Variant | Label | Wait type | Когда срабатывает |
|---|---|---|---|
RowLock | row_lock | Lock | Ожидание tuple-level lock. |
PageLock | page_lock | Lock | Ожидание page-level latch. |
TableLock | table_lock | Lock | Ожидание relation-level lock для DDL/lock manager. |
TransactionLock | transaction_lock | Lock | Ожидание commit/finish другой транзакции. |
PredicateLockAcquire | predicate_lock_acquire | Lock | Ожидание захвата predicate lock для SSI foundation. |
PredicateConflictCheck | predicate_conflict_check | Lock | Ожидание проверки predicate conflict graph. |
PageRead | page_read | IO | Чтение heap/index page при cache miss. |
PageWrite | page_write | IO | Write-back страницы при checkpoint или eviction. |
WalFlush | wal_flush | IO | WAL flush / fsync path. |
Fsync | fsync | IO | Прочие fsync пути: catalog, FPI и смежные операции. |
WalSync | wal_sync | IO | Strict WAL sync wait в durability path. |
WalGroupCommit | wal_group_commit | IO | Ожидание group commit batch. |
ColumnarCompaction | columnar_compaction | IO | Background compactor ждёт disk I/O или manifest append mutex в compact_l0_to_l1(). |
ClientRead | client_read | Net | Чтение из client socket. |
ClientWrite | client_write | Net | Запись в client socket. |
ReplicaRead | replica_read | Net | Чтение из replica connection. |
ReplicaWrite | replica_write | Net | Запись в replica connection. |
NetRead | net_read | Net | Generic network read. |
NetWrite | net_write | Net | Generic network write. |
CpuRun | cpu_run | CPU | Сессия исполняется на CPU, это не блокировка. |
PageDecompression | page_decompression | CPU | CPU time на decompression страницы при buffer-pool miss. |
PageCompression | page_compression | CPU | CPU time на compression dirty page перед flush. |
AdmissionQueue | admission_queue | Scheduler | Ожидание admission control queue. |
IoSchedulerQueue | io_scheduler_queue | Scheduler | Ожидание I/O scheduler queue. |
MemoryGrantQueue | memory_grant_queue | Scheduler | Ожидание memory grant. |
BufferPoolEviction | buffer_pool_eviction | Scheduler | Сессия ждёт свободный или evictable buffer-pool slot. |
BackpressureThrottle | backpressure_throttle | Scheduler | Unified backpressure coordinator throttles caller. |
DiskRestartHarness | disk_restart_harness | Scheduler | Test harness ждёт re-hydration on-disk state при disk-restart тесте. |
QosQueue | qos_queue | Scheduler | Async task стоит в per-shard DRR queue QoS scheduler до dispatch. |
QosBlocking | qos_blocking | Scheduler | Blocking task ждёт dispatch через QoS blocking path. |
QoS события RM-0.6.4.10
qos_queue означает, что задача уже классифицирована по service level
(critical, interactive, background) и ожидает dispatch в scheduler queue.
Рост этого wait обычно указывает на scheduler saturation или burst нагрузки.
qos_blocking означает, что задача попала в blocking path QoS scheduler.
Смотрите его вместе с gauge angarabase_qos_blocking_inflight и
angarabase_spawn_blocking_max: если blocking wait растёт, а inflight близок к
лимиту, cluster pressure находится не в SQL locks, а в runtime/blocking pool.
В Sprint 2A granularity по service level намеренно coarse: нет отдельных
qos_queue_critical, qos_queue_interactive, qos_queue_background.
Для уровня сервиса используйте QoS counters:
angarabase_qos_queued_*_total и angarabase_qos_rejected_*_total.
Ordinals и compatibility
Ordinals append-only и закреплены в WaitEvent::ordinal():
QosQueueимеет ordinal28;QosBlockingимеет ordinal29.
Массив WaitEvent::ALL используется для рендера всех label values в metrics.
Фиксированный размер metrics array задаётся N_WAIT_EVENT_VARIANTS.
Правила совместимости:
- добавление variant — non-breaking;
- удаление variant — breaking;
- renumbering ordinal — breaking;
- переименование label value из
as_str()— breaking для dashboards и alerts.
Per-session wait events (RM-0.6.4.19 Track C C1)
Начиная с RM-0.6.4.19 angara_stat_wait_events поддерживает per-session режим:
-- Process-wide aggregates (как раньше):
SELECT * FROM angara_stat_wait_events;
-- Per-session счётчики текущей сессии:
SELECT * FROM angara_stat_wait_events WHERE session_id = current_session();
В per-session режиме:
total— суммарное число входов в данный wait event для текущей сессии с момента её запуска.activeиtotal_duration_us— всегда0в phase 1 (per-session histogram deferred to phase 2).- Счётчики инкрементируются через
WaitEventGuard::enterи хранятся вAtomicWaitState::event_counts(per-session registry, indexed by session_id).
Если сессия не совершала ни одного wait event, все total = 0 (пустой wait state возвращает нули).
Метрики
Для каждого события экспортируются три Prometheus series с label
event=<variant_snake_case>:
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_wait_events_total | counter | Сколько раз код входил в ожидание этого типа. |
angarabase_wait_events_active | gauge | Сколько ожиданий этого типа активно прямо сейчас. |
angarabase_wait_event_duration_seconds | histogram | Распределение длительности ожидания. |
Histogram buckets в секундах: 0.001, 0.005, 0.01, 0.05, 0.1,
0.5, 1, 5, +Inf.
PromQL примеры
Top-N wait classes по накопленному времени за 5 минут:
topk(
5,
rate(angarabase_wait_event_duration_seconds_sum[5m])
)
Активные ожидания прямо сейчас:
sum by (event) (angarabase_wait_events_active)
p99 latency для buffer-pool eviction:
histogram_quantile(
0.99,
rate(angarabase_wait_event_duration_seconds_bucket{event="buffer_pool_eviction"}[5m])
)
Backpressure throttle rate:
rate(angarabase_wait_events_total{event="backpressure_throttle"}[1m])
QoS queue wait rate:
rate(angarabase_wait_events_total{event="qos_queue"}[5m])
p95 ожидания в QoS queue:
histogram_quantile(
0.95,
rate(angarabase_wait_event_duration_seconds_bucket{event="qos_queue"}[5m])
)
Активные blocking waits QoS:
angarabase_wait_events_active{event="qos_blocking"}
Alert на длительную очередь QoS:
histogram_quantile(
0.99,
rate(angarabase_wait_event_duration_seconds_bucket{event="qos_queue"}[5m])
) > 0.5
Alert на blocking pool pressure:
angarabase_wait_events_active{event="qos_blocking"} > 0
and
angarabase_qos_blocking_inflight > 0
Корреляция QoS waits с rejections:
rate(angarabase_wait_events_total{event="qos_queue"}[5m])
and
sum(rate({__name__=~"angarabase_qos_rejected_.*_total"}[5m])) > 0
Operator playbook
BufferPoolEviction растёт:
- buffer pool меньше рабочего набора;
- достигнут
max_cached_pages; - проверьте buffer-pool-pressure runbook.
BackpressureThrottle растёт:
- WAL queue или buffer pool exhaustion замедляет клиентов;
- проверьте
angarabase_buffer_pool_uncommitted_pages_ratio; - сопоставьте с WAL group-commit latency.
WalFlush или WalSync p99 выше 100 ms:
- вероятна fsync regression или storage stall;
- используйте wal-fsync-slow runbook.
RowLock имеет высокие duration:
- ищите lock contention и long transactions;
- используйте deadlock-spike runbook.
QosQueue растёт:
- проверьте
angara_stat_qos_queues; - смотрите
angarabase_qos_rejected_*_total; - снизьте concurrency batch jobs;
- переведите тяжёлые jobs в
SET service_level = 'background'; - пересмотрите
ANGARABASE_QOS_WEIGHTSиANGARABASE_QOS_MAX_QUEUED.
QosBlocking растёт:
- проверьте
angarabase_qos_blocking_inflight; - проверьте
angarabase_spawn_blocking_max; - ищите blocking workload, который вытесняет runtime capacity;
- не лечите это увеличением SQL lock timeout: wait находится в scheduler/runtime path.
Source of truth
- Code:
crates/angarabase/src/observability/wait_events.rs - Per-session dispatch:
crates/angarabase/src/virtual_catalog.rs+virtual_catalog/shared_catalog.rs - Metrics:
crates/angarabase/src/metrics/core.rs - Render:
crates/angarabase/src/metrics/render.rs - QoS scheduler:
crates/angarabase/src/qos_manager.rs - RM:
docs/planning/v0.6/RM-0.6.3.9.md§S11,docs/planning/v0.6/RM-0.6.4.10.md,docs/planning/v0.6/RM-0.6.4.19.mdTrack C C1
Resource Advisors v0
AngaraBase 0.6.3.9 §S10 — single-node, in-process advisors. Closes the Article #5 review finding “RFC-2026-010 ↔ runtime drift”.
This page documents the two minimum-viable advisors that ship with
0.6.3.9 — the AIMD checkpoint IoAdvisor and the RSS-sensor
MemoryAdvisor — together with the metrics they expose and the
guarantees they explicitly do not make. The full AngaraTuner
Resource Broker (distributed, QoS-weighted, schema-aware) remains a
future train (RM-0.7.0 / RM-0.8.0); RM-0.6.3.9 promotes only the
single-node sensor stubs called out as [Future] in
RFC-2026-010 §3 to Current v0.
Why advisors at all
Modern databases self-tune — Postgres auto_explain + extension-based
tuners, SQL Server’s automatic plan correction, Oracle’s adaptive
execution. AngaraBase’s long-term plan is to collapse the ~60
operator knobs down to ~10–15 budgets (memory_budget, io_budget,
cpu_budget) plus QoS policies, with an in-process broker computing
the rest.
For 0.6.3.9 we ship just enough of that vision to:
- anchor the public Article #5 narrative (no more “future-only” advisors), and
- give downstream code (plan-cache eviction, future spill paths) a stable hint API to consume now without committing to the full broker contract.
IoAdvisor — AIMD checkpoint throttler
Algorithm
Single-knob AIMD over observed flush IOPS, ticked once per attempted
checkpoint (the CheckpointWorker::with_io_advisor integration path):
on tick(observed_iops):
if observed_iops > iops_threshold:
batch_size *= decrease_factor # multiplicative-decrease, >= min
decision = throttle
else:
batch_size += increase_step # additive-increase, <= max
decision = recover
if batch_size unchanged:
decision = hold
Defaults (crates/angarabase/src/storage/advisors/io.rs,
IoAdvisorConfig::default):
| Knob | Default | Notes |
|---|---|---|
initial_batch_size | 64 pages | Resets to this on restart (no persistence) |
min_batch_size | 8 pages | Hard floor |
max_batch_size | 1024 pages | Hard ceiling |
iops_threshold | 5 000 IOPS | Above → multiplicative-decrease |
decrease_factor | 0.5 | Clamped into (0.0, 1.0) |
increase_step | 8 pages | Additive-increase per tick |
Metrics
angarabase_io_advisor_current_batch_size(gauge, pages): the advisor’s currently recommended checkpoint batch size.angarabase_io_advisor_decisions_total{action="throttle"|"recover"|"hold"}(counter): split by AIMD decision. Sum reproduces the historical decision count.
What v0 does not do
- It does not yet enforce the recommended batch size — the periodic
checkpoint flush still drains every dirty page ≤
target_lsnto preserve the completion invariant (RFC-2026-073 §S12). Wiring the recommendation into the flush path is tracked inDEBT_REGISTERas a follow-up. - It does not consider latency, only IOPS — adaptive io_uring queue depth (TD-2026-0122) is the v1 follow-up.
- It does not persist its state across restarts.
MemoryAdvisor — RSS sensor
What it samples
On every sample() call (driven by the same checkpoint worker tick on
Linux):
- read
process_rssfrom/proc/self/statm(pages * sysconf(_SC_PAGESIZE)), - compute
ratio = process_rss / configured_limit, - publish
angarabase_memory_pressure_ratiogauge, - emit a
WARNlog line ifratio >= warn_threshold(default0.8).
limit_bytes = 0 disables the advisor: is_under_pressure() returns
false and the gauge stays at 0. Non-Linux platforms always
return None from sample() in v0 (portable sensor is a follow-up).
Hint API
#![allow(unused)]
fn main() {
let advisor: Arc<MemoryAdvisor> = ...;
if advisor.is_under_pressure() {
// shed load: e.g. evict from plan cache, fall back to spill plan
}
}
The check is a single relaxed atomic load — safe to call on the hot path. The decision of what to do under pressure is intentionally left to each subsystem so the advisor itself stays narrow.
Metrics
angarabase_memory_pressure_ratio(gauge, float in[0.0, 8.0]): most recentprocess_rss / limit_bytesratio. Hard-clamped to 8.0 to bound the impact of bogus RSS reads.
Recommended PromQL
# Checkpoint throttling intensity over the last 5m
rate(angarabase_io_advisor_decisions_total{action="throttle"}[5m])
# Memory pressure crossing the warn threshold
angarabase_memory_pressure_ratio > 0.8
# Current checkpoint batch recommendation, for capacity dashboards
angarabase_io_advisor_current_batch_size
Operator playbook
| Symptom | What to check | Action |
|---|---|---|
io_advisor_current_batch_size stuck at min_batch_size | rate(io_advisor_decisions_total{action="throttle"}[5m]) consistently > 0 | Storage IOPS budget is the bottleneck. Either provision more IOPS or raise iops_threshold after measuring sustained capacity. |
memory_pressure_ratio > 0.9 for > 5m | RSS growth pattern; per-subsystem memory metrics | Consider lowering max_cached_pages or query_memory_limit_mb. Plan cache eviction will start consulting is_under_pressure() as the consumer-side wiring lands. |
io_advisor_decisions_total{action="hold"} ≫ throttle/recover | Workload is stable around the threshold | No action — AIMD is doing its job. |
Compatibility contract
- Metric names (
angarabase_io_advisor_*,angarabase_memory_pressure_ratio) are stable within the 0.6.x series. Adding new advisors or newaction=label values is a non-breaking change. - The Rust API (
IoAdvisor::tick,MemoryAdvisor::sample,MemoryAdvisor::is_under_pressure) is internal (pubfor cross-crate wiring, but not stabilised for downstream consumers outside the AngaraBase workspace). - The full AngaraTuner Resource Broker (RFC-2026-010 Phase 1+2) will coexist with v0 and may layer over these advisors; v0 metric names will continue to be emitted for backwards compatibility.
Cross-references
Backpressure Coordinator
AngaraBase 0.6.3.9 §S5+§S9 — unified backpressure surface.
This page documents how AngaraBase decides to slow down (or refuse) write work when one of its internal queues is at risk of overflowing, and the single Prometheus surface operators should use to investigate it.
Why a coordinator
Up to v0.6.3.8 the storage layer carried three independent backpressure mechanisms:
- The
buffer_pool.uncommitted_pages_ratio_hardthreshold (write transactions blocked until the writeback worker drains the uncommitted-pages set). - The high-priority I/O queue depth (low-priority prefetch dropped when OLTP demand reads saturate the I/O scheduler).
- The buffer pool capacity waiter introduced in §S2+§S8 (writers blocked when no frame can be evicted).
Each mechanism had its own metric and ad-hoc decision logic. There was no single answer to the operator question:
Why is the database refusing my write right now?
Starting with RM-0.6.3.9 the same three mechanisms remain (each as an
isolated BackpressureSource), but they are evaluated through one
BackpressureCoordinator façade and report through one unified
metric family.
Decision model
Each source returns one of three decisions on every coordinator evaluation:
| Decision | Meaning | Typical caller reaction |
|---|---|---|
pass | Source reports no pressure; the request may proceed without delay. | Continue. |
throttle | Source reports elevated pressure; the caller should slow down. | Block on a WaitEventGuard for BackpressureThrottle. |
reject | Source reports critical pressure; the request must be rejected. | Surface a 53400 INSUFFICIENT_RESOURCES error. |
The coordinator’s combined decision uses a strict dominance rule:
reject > throttle > pass
That is, any source reporting reject wins immediately, and any source
reporting throttle wins over a passing source. This mirrors the
fail-fast / block semantics that already existed for the
buffer_pool.backpressure.mode knob (see
runtime_settings.md).
Sources
| Source label | Signal | Tunable knob |
|---|---|---|
uncommitted_pages | Fraction of buffer-pool frames carrying uncommitted page-image deltas. | buffer_pool.uncommitted_pages_ratio_hard (default 0.30). |
wal_queue | High-priority I/O queue depth (OLTP demand reads above the saturation watermark). | (internal, default threshold 4) |
buffer_pool | Buffer-pool capacity waiter (max_cached_pages exhausted, no evictable frame). | buffer_pool.pool_wait_timeout_ms (default 5000). |
The buffer_pool source reports reject when the pool is over capacity
(an eviction failed because every frame is currently pinned) and
throttle when a writer is parked on the capacity cv. The two conditions
are tracked independently of each other.
BREAKING (RM-0.6.3.9 §S5+§S9, decision #5): the
buffer_pool.uncommitted_pages_ratio_hardknob was previously nameduncommitted_dirty_ratio_hard. The legacy identifier is removed without a compatibility alias — operators upgrading from v0.6.3.8 or earlier must rename the key in their config files. The release entry for RM-0.6.3.9 indocs/planning/releases/v0/RELEASE_NOTES.mdcontains the migration note.OPERATOR-UX hardening (2026-04-20, RM-0.6.3.10, closes F-UX-1 + OQ-2026-054 + TD-2026-0175): the parser is now fail-closed on the legacy key. A config that still contains
[buffer_pool] uncommitted_dirty_ratio_hard = …will refuse to start withexit 78(EX_CONFIG) and an operator-facing message naming the renamed key. Unknown keys (typos, future-feature backports) emit a structuredtracing::warn!(target = "config", section, key)and increment the counterangarabase_config_unknown_keys_total— recommended alert:> 0after a fresh deploy. Soft-deprecated aliases ([server] host/port,[storage] wal_directory) remain silently recognized for compatibility.
Metrics
All metrics are emitted on the standard /metrics endpoint
(see observability.md).
| Metric | Type | Labels | Meaning |
|---|---|---|---|
angarabase_backpressure_throttle_decisions_total | counter | source, decision | Per (source × decision) counter incremented on every coordinator evaluation. |
angarabase_backpressure_active_sources | gauge | — | Number of sources currently reporting non-pass (snapshot, refreshed on every evaluation). |
Label sets are stable across releases:
source∈ {uncommitted_pages,wal_queue,buffer_pool}decision∈ {pass,throttle,reject}
PromQL recipes
Detect any active backpressure right now:
angarabase_backpressure_active_sources > 0
Decision rate by source over the last 5 minutes:
sum by (source) (
rate(angarabase_backpressure_throttle_decisions_total{decision!="pass"}[5m])
)
Reject rate (the operator pager-worthy signal):
sum(rate(
angarabase_backpressure_throttle_decisions_total{decision="reject"}[5m]
))
Operator playbooks
| Symptom | First check | Next step |
|---|---|---|
angarabase_backpressure_active_sources >= 1 for >30 s | Which source label dominates the decision counters? | Follow per-source playbook below. |
source="uncommitted_pages",decision="throttle" rate climbing | buffer_pool_uncommitted_dirty_ratio near buffer_pool.uncommitted_pages_ratio_hard? | Increase buffer pool size, or shrink concurrent write batch sizes. |
source="wal_queue",decision="throttle" rate climbing | angarabase_io_advisor_current_batch_size shrinking? (correlated) | Investigate disk saturation; throttle prefetch / background warmup. |
source="buffer_pool",decision="reject" non-zero | angarabase_buffer_pool_over_capacity_pages > 0? | Pinned-page leak is suspected — capture a diagnostics bundle and open an incident. |
Compatibility contract
- The
(source, decision)label sets above are part of the public Prometheus contract and will only change in a major release. - Adding a new source or decision is backward-compatible; removing or
renaming requires a deprecation cycle documented in
CHANGELOG.md. - Coordinator dominance order (
reject > throttle > pass) is part of the contract: alerts may rely on it.
Vector Observability
AngaraBase 0.6.3.10 §S17 — closes the RFC-2026-151 §7a Observability Contract that was deferred from RM-0.6.2.9 G2 (Sprint 4 G2-001 disposition). User direction 2026-04-20 «extended scope» — close before the HTAP column-store train (RM-0.6.4.0).
This page documents the vector executor observability surface: 3 USDT
probes on the hot path, 1 selection-ratio histogram exposed via /metrics,
and the operator playbooks that turn those signals into rewrite / index
decisions.
Surface summary
| Surface | Type | Source |
|---|---|---|
angarabase:vector_batch_start | USDT probe | crates/angarabase/src/observability/probes.rs |
angarabase:vector_batch_end | USDT probe | crates/angarabase/src/observability/probes.rs |
angarabase:vector_fallback | USDT probe | crates/angarabase/src/observability/probes.rs |
angarabase_vector_selection_ratio | Prometheus histogram | crates/angarabase/src/metrics/core.rs |
angarabase_vector_fallback_total | Prometheus counter (existing) | crates/angarabase/src/metrics/core.rs |
angarabase_vector_rows_produced_total | Prometheus counter (existing) | crates/angarabase/src/metrics/core.rs |
The probes carry the inline #[cfg(feature = "usdt")] guard, so non-usdt
builds (WASM, slim test profiles) pay zero instructions per call. RFC-2026-369
remains the canonical source for the broader USDT/eBPF probe infrastructure;
this page covers only the vector-executor-specific subset finalised by S17.
USDT probes
All three probes use provider name angarabase and follow the
<subsystem>_<event> convention. Numeric discriminants for every enum
argument are append-only — adding a new variant is non-breaking, but
renumbering or removing one requires an RFC update.
vector_batch_start(operator_kind: u8, batch_size: u32, source: u8)
Fired at the entry of VectorOperator::next_batch() for every primary
operator (Filter / SeqScan / IndexScan / Bridge / ParallelSeqScan).
operator_kind—ProbeVectorOperatorKinddiscriminant. Stable values:Filter=0,SeqScan=1,IndexScan=2,Bridge=3,ParallelSeqScan=4,HashJoin=5(reserved),Aggregate=6(reserved),Project=7(reserved).batch_size— upstream batch length in rows.source—ProbeVectorBatchSourcediscriminant. Stable values:HeapScan=0,IndexScan=1,UpstreamVector=2,ParallelMorsel=3.
vector_batch_end(operator_kind: u8, rows_produced: u32, rows_filtered: u32, duration_us: u64)
Fired at the exit. rows_filtered is the count dropped by this operator;
rows_produced is the count emitted to the next operator. duration_us is
the wall-time of the call, including any upstream next_batch() recursion.
vector_fallback(plan_kind: u8, reason: u8)
Fired wherever the planner / executor falls back to the row path.
plan_kind—ProbeOperatordiscriminant (best-effort tag for the plan node that tripped the fallback; e.g.HashProbe=4,Aggregate=7).reason—ProbeVectorFallbackReasondiscriminant. Stable values:UnsupportedPlan=0,TypeError=1,NonEquiJoin=2,BudgetExceeded=3,FeatureDisabled=4.
Wire contract notice. S17 finalises the
vector_fallbackargument shape, replacing the legacy ad-hoc(u64, u64)literals that the S9-D4 code shipped with. RFC-2026-369 was open at S17 close so no production bpftrace consumers were broken; new consumers MUST use theProbeOperator×ProbeVectorFallbackReasonmapping.
bpftrace recipes
# Live histogram of post-Filter selectivity (per-batch, last 60 s).
usdt:./angarabased:angarabase:vector_batch_end /arg0 == 0/ {
@sel = hist(arg1 * 100 / (arg1 + arg2));
}
# Top fallback reasons in the last hour.
usdt:./angarabased:angarabase:vector_fallback {
@[arg0, arg1] = count();
}
# Vector hot-path call rate by operator.
usdt:./angarabased:angarabase:vector_batch_start {
@[arg0] = count();
}
Self-test scripts live under tools/usdt/ (per the standing convention from
RFC-2026-369 §4 — bpftrace -l 'usdt:./angarabased:angarabase:*').
Histogram: angarabase_vector_selection_ratio
Cumulative Prometheus histogram (HELP / TYPE headers emitted on every
scrape) tracking the per-batch ratio rows_produced / rows_scanned observed
by VectorFilterV0::next_batch().
Bucket scheme (compatible with histogram_quantile()):
[0.001, 0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 1.0, +Inf]
The +Inf bucket exists for protocol compliance only — selection ratio is
bounded to [0.0, 1.0] by construction (kept ≤ scanned enforced inside
apply_predicate). Empty batches (rows_scanned == 0) carry no signal and
are silently dropped by VectorSelectionRatioHistogram::observe().
The histogram is rendered alongside the existing wait-event histogram by
render_prometheus() and is covered by:
metrics::render::tests::vector_selection_ratio_histogram_appears_in_prometheus_output_rm06310_s17(exposition-shape test);metrics::render::tests::vector_selection_ratio_histogram_observe_buckets_rm06310_s17(bucket-edge test, independent of the renderer).
PromQL examples
# Median Filter selectivity over the last 5 minutes.
histogram_quantile(
0.5,
rate(angarabase_vector_selection_ratio_bucket[5m])
)
# Share of batches with extremely-low selectivity (≤ 5 %).
sum(rate(angarabase_vector_selection_ratio_bucket{le="0.05"}[5m]))
/
sum(rate(angarabase_vector_selection_ratio_count[5m]))
# Mean selectivity (sum / count, both already rate-friendly).
rate(angarabase_vector_selection_ratio_sum[5m])
/
rate(angarabase_vector_selection_ratio_count[5m])
Operator playbook
| Observation | Likely diagnosis | Recommended action |
|---|---|---|
p50 ≥ 0.9 consistently | Filter is essentially a no-op; predicate could be pushed down or removed entirely | Review query plan: candidate for filter pushdown to scan / index level; rewrite query |
p95 ≤ 0.05 and high vector_batch_start rate | Index missing — Filter is throwing away ≥ 95 % of every batch | Run ANALYZE; add an index on the predicate columns; verify with EXPLAIN |
p99 = 1.0 only on a small set of queries | Selective predicate fires occasionally on a hot table | Acceptable; consider partial index if the predicate is stable |
vector_fallback rate spike | A new query shape is tripping the row-path fallback | Filter vector_fallback{reason=…} — match against ProbeVectorFallbackReason |
Cross-reference runbooks/buffer-pool-pressure.md for I/O-side correlation
and the future commit-latency-tuning.md (Track B S13) for write-path
overlay.
Source-of-truth contract
| Artifact | Role |
|---|---|
RM-0.6.3.10 §S17 | Sprint contract (this page is the operator-facing rendering) |
RFC-2026-151 §7a Observability Contract | Long-form design (closed by S17) |
RFC-2026-369 USDT/eBPF Observability Probes | Broader probe taxonomy (open at S17 close — soft prereq) |
crates/angarabase/src/observability/probes.rs | USDT macro definitions + enum stability tests |
crates/angarabase/src/metrics/core.rs::VectorSelectionRatioHistogram | Histogram storage + observe() API |
crates/angarabase/src/metrics/render.rs::render_vector_selection_ratio | Prometheus exposition |
crates/angarabase/src/query/vector.rs::VectorFilterV0::next_batch | Single observation point (Filter operator boundary) |
jemalloc Heap Profiling Runbook
Операторский runbook для memory/heap анализа на базе jemalloc.
Каноничный источник: этот runbook в angarabook/src/operations/.
Scope
- feature:
jemalloc-prof(opt-in); - метрики heap-фрагментации;
- on-demand profiling в staging/debug;
- leak-check для длительных прогонов (Golden DB).
Build and verify
cargo build --release --features jemalloc-prof
curl http://localhost:9091/metrics | rg jemalloc
Key metrics
angarabase_jemalloc_allocated_bytesangarabase_jemalloc_resident_bytesangarabase_jemalloc_active_bytesangarabase_jemalloc_mapped_bytesangarabase_jemalloc_fragmentation_ratio
Практическая интерпретация:
~1.0: низкая фрагментация;>1.5: риск фрагментации;>2.0: требуется разбор memory path.
Heap profiling workflow
- Запуск с
MALLOC_CONF=prof:true,.... - Сигнал
SIGUSR1для forced dump. - Анализ
jeprof(text/pdf/diff).
Leak-check for long-lived runs
Golden DB flow:
tools/golden_db/manage.sh leak-check baseline- длительная нагрузка
tools/golden_db/manage.sh leak-check report
Сравниваются baseline/after по allocated/resident/mapped и fragmentation.
Related references
tools/golden_db/manage.shsrc/operations/golden-dataset.md
Parallel Runtime Observability Runbook
Операторский runbook для диагностики регрессий в AngaraParallel.
Каноничный источник: этот runbook в angarabook/src/operations/.
Goal
Быстро определить источник падения QPS/роста latency без deep-debug в коде:
- planner/plan shape;
- runtime/scheduler pressure;
- storage/IO contention.
Fast triage
- Сверить bench-метрики и серверные метрики в одном временном окне.
- Проверить QPS, p95/p99, queue depth, lock waits, error-rate.
- Классифицировать проблему: planner vs runtime vs storage.
Required signals
- USDT:
probe_parallel_query_startprobe_morsel_dispatchedprobe_morsel_completed- Prometheus minimum:
angarabase_storage_io_read_duration_ms_*angarabase_storage_io_write_duration_ms_*angarabase_pgwire_pool_queue_depthangarabase_lock_wait_duration_ms_*angarabase_slow_query_total
Incident playbook
- Снять baseline и regression run на одном профиле.
- Собрать
EXPLAIN ANALYZEдля медленных запросов. - Проверить, что используется ожидаемый parallel path:
workers_planned,workers_launched,Vector*operators иreason_codes. - Сопоставить dispatch/completion с tail latency.
- Проверить memory guardrails и деградацию вместо hard-fail.
- Зафиксировать short report: impact, suspect component, next action.
Дальше
- How to read query plans — подробная расшифровка
workers_planned,workers_launched,Vector*и optimizer diagnostics. - Performance tuning guide — общие подходы к тюнингу под параллелизм.
- Observability metrics checklist — общие метрики, в которые встроены параллельные счётчики.
AngaraReplica v2 Operations Guide
Краткий операторский guide для streaming replication v2.
Каноничный источник: этот runbook в angarabook/src/operations/.
Topology and scope
- 1 primary + до 8 standby (async replication).
- Standby работает в read-only режиме (
SQLSTATE 25006на write). - Promote выполняется вручную (auto-failover в следующей major line).
Configuration baseline
Primary:
[replication].role = "primary"listen_addrwal_retention_segments
Standby:
[replication].role = "standby"primary_addrslot_namewal_path
Operations flow
- Запуск primary.
- Запуск standby и проверка lag-метрик.
- Мониторинг replication lag / reconnects / slots.
Promote (manual failover)
- Promote должен завершиться через sync-checkpoint handshake.
- Таймаут promote fail-closed (standby не принимает writes, если handshake не завершился).
- Lease-based fencing снижает риск split-brain, но не заменяет полноценно STONITH/Raft.
Key monitoring signals
angara_node_is_standbyangara_replication_lag_bytesangara_replication_lag_msangara_replication_reconnects_totalangara_promote_totalangara_promote_duration_ms_last
Typical incidents
- Standby не подключается: адрес/порт/firewall/reconnects.
WAL segment gone: нужен base backup и restart standby.- Promote timeout: проверить сеть и WAL write path на primary.
Дальше
- Disaster recovery playbook — DR-сценарии поверх репликации.
- Backup and restore (operator-level) — как репликация дополняет (не заменяет) backup.
- Operational policies baseline — соглашения SLA/RTO/RPO, в рамках которых работает replication v2.
Security Context Propagation
Starting with RM-0.6.7.0, the security context (including tenant_id) is automatically propagated through the WAL replication stream.
Key Features
- Tenant Isolation: The
tenant_idis embedded in WAL records, ensuring that standby nodes maintain the same multi-tenancy boundaries as the primary. - Integrity Verification: Replication tokens are protected by CRC32C checksums.
- Fail-Closed Security: If a tampered or invalid token is detected during replication, the connection is immediately terminated to prevent unauthorized data access.
Operational Policies Baseline
Краткий свод операционных политик релизной дисциплины.
Breaking changes policy (v1.*)
Default для minor trains: избегать breaking-изменений.
Если breaking неизбежен, обязателен пакет:
- RFC/design note;
- migration notes;
- release notes с impact/steps.
Для on-disk изменений требуется строгий upgrade-дисциплина:
- обновить
crates/angarabase/src/on_disk.rs; - обновить
src/operations/upgrade-and-migration.md; - приложить upgrade rehearsal evidence.
Breaking budget registry
Реестр breaking surfaces должен явно фиксировать:
- статус (
no change/changed with notes/planned); - evidence path;
- обновления в рамках каждого train с потенциальным impact.
SLO/SLA methodology
Измерения строятся на воспроизводимом профиле и pinned evidence:
- latency;
- throughput;
- saturation/backpressure signals.
Runner baseline:
tools/perf_pack/run.sh
Evidence policy
- Heavy artifacts: локально в
artifacts/.... - Pinned evidence: компактные отчёты в
docs/planning/evidence/.... - RM/release notes ссылаются только на pinned evidence.
Triage entry points
src/operations/observability-metrics.mdsrc/operations/troubleshooting.md
Дальше
- Configuration schema reference — конкретные ключи, на которые ссылаются политики.
- Security operations baseline — security-часть operator-политик.
- Testing and validation baseline — как политики верифицируются в CI.
Client Compatibility Baseline
Операторский baseline по совместимости клиентов/ORM.
Каноничный источник: этот runbook в angarabook/src/operations/.
Supported Framework Matrix (RM-0.6.5.7)
| Framework / Driver | Version | Status | Notes |
|---|---|---|---|
| psql | any | ✅ Supported | baseline |
| psycopg3 | 3.3.4 | ✅ Supported | Fixed in v0.6.5.3: EQP cast/arithmetic, date/timestamp encoding, IS NULL, = ANY(ARRAY). Fixed in v0.6.5.5: correct OID mapping and UTC serialization. Fixed in v0.6.5.7: DATE type (OID 1082, binary i32), bool comparison (1=2 → false), FK DDL accept (NOT ENFORCED), multi-col CREATE INDEX accept |
| Django ORM + psycopg3 | 5.x | ✅ Supported | Basic migrations PASS; EQP gaps fixed in v0.6.5.3. Fixed in v0.6.5.5: set_config/obj_description stubs unblock introspection. |
| Odoo 19 (community) | 19.x | ✅ Supported | Fixed in v0.6.5.3: IS NULL, = ANY(ARRAY), pg_class filter, pg_index, CREATE SEQUENCE. Fixed in v0.6.5.5: GAP-C2 (UPDATE SET func), GAP-C5 (date_trunc). |
| sqlx | 0.8.6 | ✅ Supported | Fixed in v0.6.5.3: ParameterDescription in Describe(S) |
| tokio-postgres (simple query) | 0.7.17 | ✅ Supported | Simple query protocol |
| tokio-postgres (extended query) | 0.7.17 | ✅ Supported | Fixed in v0.6.5.3: ParameterDescription in Describe(S). Fixed in v0.6.5.7: binary encode for DATE/TIMESTAMP, binary param decode OID 1114/1184, ParameterDescription returns real OIDs from Parse |
Goal
Удерживать repeatable compatibility baseline для:
psql- DBeaver
- Odoo-shaped probes
и отслеживать regressions через pinned воспроизводимые проверки.
Phase A focus (Odoo)
- Runtime smoke без критических SQL-ошибок.
- Stable trace replay без shape/protocol regressions.
- Явная граница между допустимыми shape-stubs и недопустимыми semantic-unsafe stubs.
Pinned tooling
tools/pg_catalog_trace/run_odoo_stages_angara.shtools/pg_catalog_trace/extract_angara_trace.pytools/pg_catalog_trace/replay_angara_trace.shtools/compat_suite/run.sh --nightly --runs 3tools/compat_suite/run.sh --odoo --runs 3
High-signal checks
- SQLSTATE mapping (
42601,0A000) стабилен. - Catalog/info_schema формы ответов стабильны для probe-набора.
- Odoo/DBeaver smoke-путь не ломается от изменений в
pg_catalog.
Regression triage
Артефакты compat-suite:
summary.jsoniter_<N>/summary.jsoniter_<N>/test_<name>.log
Function Compatibility (RM-0.6.5.5)
Для поддержки ORM (Django, Odoo) добавлены следующие функции:
set_config(name, value, is_local): Stub, возвращаетvalue. Позволяет Django настраиватьTimeZoneиsearch_pathбез ошибок.obj_description(oid, catalog): Stub, возвращаетNULL. Позволяет Django выполнять интроспекцию базы данных.date_trunc(field, timestamp): Полная реализация. Поддерживает все стандартные поля (year,month,day,hourи т.д.).NOW(),CURRENT_TIMESTAMP: Возвращают текущее время в UTC.
DML Compatibility (RM-0.6.5.5)
UPDATE SET col = func_call(): Теперь поддерживается использование функций (например,write_date = NOW()) и явных приведений типов (col = val::type) в клаузеSET. Это критично для Odoo 19.
Query Execution & Bug Fixes (RM-0.6.5.7)
- Bool comparison: Сравнение констант разных типов теперь корректно приводится к boolean.
Пример:
SELECT 1 = 2;возвращаетf(ранее могло вызывать ошибку типов).
Поддерживаемые типы (RM-0.6.5.7)
date: Нативный тип. OID 1082. Binary mode: BE i32 (days since 2000-01-01). Text mode: ISO-8601 (YYYY-MM-DD).current_dateподдерживается. Пример:SELECT '2026-05-08'::date;timestamp: Нативный тип. OID 1114 (без зоны) / 1184 (с зоной). Binary mode: BE i64 (microseconds since 2000-01-01). Поддерживается каст строковых литералов в формате ISO-8601. Пример:SELECT '2026-05-08 12:00:00'::timestamp;
DDL Compatibility (RM-0.6.5.7)
Foreign Key Constraints
Синтаксис REFERENCES и FOREIGN KEY ... REFERENCES принимается парсером (v0.6.5.7+).
Ограничения не применяются (NOT ENFORCED). Сервер логирует [FK constraint] ... accepted as NOT ENFORCED.
Пример:
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT REFERENCES users(id) -- NOT ENFORCED
);
Multi-Column Indexes
CREATE INDEX ON t(a, b, c) принимается (v0.6.5.7+). Индекс строится только по первой колонке.
Оставшиеся колонки сохраняются в метаданных. Сервер логирует предупреждение.
Пример:
CREATE INDEX idx_multi ON my_table (col1, col2, col3); -- Строится только по col1
Known Limitations (RM-0.6.6.3)
SQL-level PREPARE / EXECUTE / DEALLOCATE
Синтаксис SQL PREPARE stmt AS ... / EXECUTE stmt(...) / DEALLOCATE stmt
не поддерживается в AngaraBase v0.6. Вернётся feature_not_supported.
Что использовать вместо: extended query protocol (Parse/Bind/Execute pgwire messages), который автоматически используется всеми поддерживаемыми драйверами:
# psycopg3 — EQP автоматически (prepare=True по умолчанию)
with conn.cursor() as cur:
cur.execute("SELECT $1::int", (42,)) # → PREPARE + BIND + EXECUTE под капотом
// JDBC
PreparedStatement ps = conn.prepareStatement("SELECT ?::int");
ps.setInt(1, 42);
# psql — использует simple query protocol; PREPARE как SQL НЕ работает.
# Для интерактивного тестирования используй \bind (psql 16+):
psql> SELECT $1::int \bind 42 \g
pg_sleep()
Функция pg_sleep(seconds) не реализована в v0.6.
Для тестирования таймаутов используй тяжёлый запрос:
SET statement_timeout = 10; -- 10 ms
SELECT count(*) FROM large_table a CROSS JOIN large_table b; -- → ERROR 57014
Protocol Compatibility (RM-0.6.5.7)
- Binary encode DATE/TS: Типы
dateиtimestampкодируются в бинарном формате как BE i32 и BE i64 соответственно. - Binary param decode: Поддерживается декодирование бинарных параметров для OID 1114 (
timestamp) и 1184 (timestamptz). - ParameterDescription OID: Сообщение
ParameterDescription(фаза Parse) теперь возвращает реальные OID типов параметров вместо нулей.
Быстрый путь:
- найти failing test в summary;
- открыть соответствующий log;
- локально воспроизвести точным
cargo testили suite-runner командой.
Testing and Validation
Операторский baseline для crash/recovery validation и связанных проверок.
Каноничный источник: этот runbook в angarabook/src/operations/.
Goal
Проверять, что recovery-путь:
- не даёт silent corruption;
- сохраняет контракт durability mode;
- остаётся идемпотентным при повторных рестартах.
Core invariants
- No silent corruption: либо корректный старт, либо явный fail с диагностикой.
- Idempotent recovery: повторный restart не меняет oracle outcome.
- Visibility safety: uncommitted изменения не становятся видимыми после recovery.
- Durability semantics:
strict: ack-commit обязан пережить crash;group_commit: ack semantics строго соответствует заявленному контракту;relaxed: возможна потеря части ack-commit в рамках контракта, но без нарушения целостности.
Minimal runner
Pinned runner:
tools/storage_poc/crash_loop.sh
Ключевые профили:
--nightly--dirty-pressure--double-restart--durability strict|group_commit|relaxed--corrupt-txlog/--corrupt-storage(fail-fast проверки)
Minimum scenarios
- SIGKILL during commit storm (tail handling).
- SIGKILL around checkpoint markers.
- Double restart idempotence.
Required artifacts
txlog_scan_*.jsontxlog_replay_*/*.jsonrecovery_summary.json(+ restart2 summary для idempotence)- machine-readable pass/fail summary для CI/nightly.
Exit criteria (operator gate)
- Все обязательные сценарии проходят.
- Артефакты валидны и доступны для triage.
- Нет нарушений инвариантов visibility/durability.
Related operations references
src/operations/backup-restore.mdsrc/operations/disaster-recovery.mdsrc/operations/diagnostics-bundle.md
Дальше
- Golden dataset management — на каких данных гоняются validation-сценарии.
- CI reproducibility contract — гарантии воспроизводимости для validation pipeline.
- Operational policies baseline — какие политики обязаны иметь validation-cover.
Golden Dataset Management
Операторский baseline для поддержки persistent Golden DB.
Каноничный источник: этот runbook в angarabook/src/operations/.
Goal
Использовать стабильный большой dataset для:
- release closure validation;
- upgrade rehearsal;
- performance drift tracking;
- soak сценариев на реалистичной нагрузке.
Canonical sources
- RFC:
RFC-2026-380-continuous-validation-infrastructure-v0 - Tooling:
tools/golden_db/manage.sh
Infrastructure baseline
- Storage:
.fastio/golden_db(NVMe). - Отдельные data/txlog пути.
- Production-like durability и бинарный WAL.
Main commands
tools/golden_db/manage.sh inittools/golden_db/manage.sh starttools/golden_db/manage.sh stoptools/golden_db/manage.sh statustools/golden_db/manage.sh grow --rows <n>tools/golden_db/manage.sh upgrade-check --binary <path>
Routine release flow
- Остановить Golden DB.
- Запустить
upgrade-checkновым бинарником на snapshot. - Проверить startup/connectivity/row-count oracle.
- Зафиксировать артефакты и итоговый verdict.
Validation tiers
- Tier 1: read compatibility (обязательный).
- Tier 2: write compatibility (planned).
- Tier 3: performance canary (planned).
Дальше
- Testing and validation baseline — как golden dataset подключается к validation pipeline.
- CI reproducibility contract — требования к воспроизводимости фикстур.
CI Reproducibility Contract
Краткий контракт воспроизводимости локальных CI-gates.
Каноничный источник: этот runbook в angarabook/src/operations/.
Goal
Сделать CI-гейты воспроизводимыми в чистом локальном окружении, чтобы снизить bus factor.
Pinned entrypoint:
tools/ci_pr.sh
Must
- Скрипт явно сообщает о требуемых инструментах.
- Запуски детерминированы там, где это возможно.
- Артефакты сохраняются в стабильные пути под
artifacts/. - Все ключевые гейты доступны через единый entrypoint.
Should
- Иметь container/dev-env вариант запуска.
- Добавить advisory/license gate (
cargo-denyи аналоги), когда это допустимо по сетевой политике.
Non-goals
- Жёсткая привязка к конкретному CI provider.
- Идентичные perf-метрики между разными машинами.
Dogfooding linkage (pilot)
Практический цикл: deploy -> smoke -> workload -> observe -> backup/restore rehearsal -> triage.
Pinned evidence paths (legacy surface):
docs/planning/evidence/archive/legacy-root-20260417/pilot/latest.mddocs/planning/evidence/archive/legacy-root-20260417/pilot/report_v0.md
Дальше
- Testing and validation baseline — какие сценарии должны быть воспроизводимы по этому контракту.
- Golden dataset management — как версии фикстур пиннятся для воспроизводимости.
Known Issues
Живой реестр известных проблем для repeatable triage.
Каноничный источник: этот runbook в angarabook/src/operations/.
Purpose
- Явно фиксировать известные gaps;
- привязывать reproducible repro + expected SQLSTATE/shape;
- упрощать release decision.
Usage rules
- Добавлять issue сразу, когда проблема воспроизводима и временно допустима.
- Предпочитать ссылку на regression test, который фиксирует ожидаемое поведение.
- Закрывать issue только после фикса + обновления tests/evidence.
Entry template (minimum)
- ID
- Area
- Severity
- Affects
- Repro
- Expected
- Observed
- Status
- Owner
- Next step
Fixed in v0.6.5.5
GAP-C2: UPDATE SET col = func() not supported
- Status: Fixed in RM-0.6.5.5.
- Summary:
UPDATE SETnow supports function calls (e.g.,NOW()) andCASTexpressions, unblocking Odoo 19 record writes.
GAP-C5: date_trunc() not implemented
- Status: Fixed in RM-0.6.5.5.
- Summary:
date_trunc(field, timestamp)is fully implemented for all standard fields, unblocking Odoo reporting.
GAP-DJ-001/002: Missing set_config() and obj_description()
- Status: Fixed in RM-0.6.5.5.
- Summary: Added stubs for
set_configandobj_descriptionto ensure Django ORM introspection and migrations work without monkey-patches.
Protocol: Timestamp UTC serialization & OID mapping
- Status: Fixed in RM-0.6.5.5.
- Summary:
TIMESTAMP WITHOUT TIME ZONEis now correctly mapped to OID 1114 and serialized in UTC without offset, fixing time-shift issues inpsycopg3.
Fixed in v0.6.5.3
GAP-RUST-001: Missing ParameterDescription in Extended Query Protocol
- Status: Fixed in RM-0.6.5.3.
- Summary:
ParameterDescription(‘t’) is now sent beforeRowDescription/NoDatafor Statement Describe, unblockingsqlxandtokio-postgresEQP.
GAP-A1: Cast expressions fail in Extended Query Protocol
- Status: Fixed in RM-0.6.5.3.
- Summary:
SELECT 1::int4and arithmetic via EQP no longer cause “vector type mismatch Utf8”.
GAP-A2: date/timestamp encoding violation in pgwire
- Status: Fixed in RM-0.6.5.3.
- Summary:
dateandtimestampvalues are returned in ISO-8601 format, not as raw integers.
GAP-C1: pg_catalog.pg_index missing
- Status: Fixed in RM-0.6.5.3.
- Summary:
pg_catalog.pg_indexnow returns an empty resultset instead of an error.
GAP-C3: IS NULL / IS NOT NULL predicates not supported
- Status: Fixed in RM-0.6.5.3.
- Summary:
IS NULLandIS NOT NULLwork in the general query path.
GAP-C4: = ANY(ARRAY[…]) not supported
- Status: Fixed in RM-0.6.5.3.
- Summary:
col = ANY(ARRAY[v1, v2, v3])now works (desugars toIN).
GAP-C6: pg_class WHERE filter bypass
- Status: Fixed in RM-0.6.5.3.
- Summary:
pg_class WHERE relname = 'foo'filter now works correctly.
GAP-C7: CREATE SEQUENCE + nextval() catalog registration
- Status: Fixed in RM-0.6.5.3.
- Summary:
CREATE SEQUENCE+nextval()works in the simple query path.
KI-2026-005: SQLSTATE leakage
- Status: Fixed in RM-0.6.5.3.
- Summary: Internal execution errors (e.g., raw
54000) are no longer leaked directly to clients and are properly mapped to standard protocol errors.
Current open issues
KI-2026-006 — SELECT ... FOR UPDATE supports only the documented single-table form
- ID:
KI-2026-006 - Area: SQL / Row locking
- Severity: Medium (application compatibility)
- Affects: clients that rely on
SELECT ... FOR UPDATEwith joins, subqueries,NOWAIT,SKIP LOCKED, orFOR SHARE - Repro:
- Prepare two simple tables:
SET search_path = public; CREATE TABLE t_lock_a (id INT); CREATE TABLE t_lock_b (id INT); INSERT INTO t_lock_a (id) VALUES (1); INSERT INTO t_lock_b (id) VALUES (1); - Run a locking query outside the documented single-table form:
SELECT t_lock_a.id FROM t_lock_a JOIN t_lock_b ON t_lock_a.id = t_lock_b.id FOR UPDATE; - Or run a lock-clause variant:
SELECT id FROM t_lock_a FOR UPDATE SKIP LOCKED;
- Prepare two simple tables:
- Expected: unsupported locking forms fail closed with SQLSTATE
0A000 feature_not_supported; parser-level incompatibility may fail earlier with SQLSTATE42601 syntax_error. - Observed: only the plain single-table
FOR UPDATEpath withidin projection is part of the documented contract. - Status: Open.
- Owner: SQL / MVCC owner
- Next step: define the full lock-clause compatibility matrix before documenting additional forms as supported.
KI-2026-004 — current_setting() returned NULL for unknown keys (fixed RM-0.6.5.1)
- ID:
KI-2026-004 - Area: SQL / Session claims
- Severity: Minor (operator UX)
- Affects: clients calling
current_setting('app.nonexistent')and expecting PostgreSQL-compatible error - Repro:
SELECT current_setting('app.nonexistent')on a session without that claim set - Expected:
ERROR: unrecognized configuration parameter "app.nonexistent"(SQLSTATE42704) - Observed: result was
NULL(silent empty result), diverging from PostgreSQL semantics - Status: Fixed (
RM-0.6.5.1 Track Z item Z4). Unit testcurrent_setting_unknown_key_returns_42704pins the fix. - Owner: Core team
- Next step: N/A — closed.
KI-2026-001 — WAL strict-mode latency on write-heavy workloads
- ID:
KI-2026-001 - Area: WAL / Commit path
- Severity: Major (performance)
- Affects: deployments with
ANGARABASE_TRANSACTION_LOG_DURABILITY=strictand frequent DML commits - Repro:
- Run write-heavy transactional workload (
INSERT/UPDATE/DELETE) in strict durability mode. - Compare commit latency against the same workload with grouped flush boundaries.
- Run write-heavy transactional workload (
- Expected: strict mode preserves durability with near-commit-boundary flush cost.
- Observed: per-record fsync amplification can inflate commit latency noticeably.
- Status: Open (tracked as
TD-2026-0184, scheduled RM-0.6.4.0) - Owner: WAL owner / Core team
- Next step: land commit-boundary fsync consolidation and re-run strict-mode benchmark pack.
KI-2026-002 — Grafana 12 UI importer fails on canonical dashboard JSON
- ID:
KI-2026-002 - Area: Observability / Dashboards
- Severity: Medium (operator UX)
- Affects: manual dashboard import through Grafana 12 UI
- Repro:
- Open Grafana 12.x and use “Import dashboard”.
- Load one of
tools/observability/grafana/*.json.
- Expected: dashboard imports via UI without manual rewriting.
- Observed: Grafana 12 UI may fail with
Cannot read properties of undefined (reading 'type'). - Status: Mitigated workaround available (
tools/observability/grafana/import/bundle, tracked byTD-2026-0163) - Owner: Observability owner
- Next step: keep canonical JSON as source of truth; for Grafana 12 manual import use the
import/bundle flow.
KI-2026-003 — No offline major-version migrator yet
- ID:
KI-2026-003 - Area: Upgrade / Operations
- Severity: Medium (operational risk)
- Affects: major upgrades that require on-disk format change
- Repro:
- Prepare data dir with one format version.
- Attempt direct startup with incompatible major format.
- Expected: supported offline migrator path for major on-disk transitions.
- Observed: fail-closed behavior works, but migration path is still dump/restore.
- Status: Open (
TD-2026-0170, linked riskR-0.6.3.11-04) - Owner: Core team
- Next step: design and implement offline migrator contract in a dedicated train.
Statistics and ANALYZE
В этом разделе описывается работа с подсистемой сбора статистики в AngaraBase.
ANALYZE
Команда ANALYZE собирает статистику о распределении данных в таблицах, которая используется оптимизатором для построения эффективных планов выполнения запросов.
Drift Detection
При выполнении ANALYZE AngaraBase использует механизм drift detection для
минимизации лишних записей в системный каталог. Если новое значение
distinct_estimate изменилось менее чем на 10% по сравнению с текущим
сохраненным значением, обновление статистики для этой колонки пропускается.
Это позволяет избежать лишнего I/O и инвалидации планов в кэше при незначительных изменениях данных.
Column Statistics и distinct_estimate
Основной метрикой для оценки селективности является distinct_estimate (аналог
n_distinct в PostgreSQL). Это оценка количества уникальных значений в колонке.
- Если
distinct_estimateравен общему количеству строк, колонка уникальна. - Если
distinct_estimateмал по сравнению с количеством строк, колонка имеет низкую кардинальность (low cardinality).
Оптимизатор (CBO) использует эти данные для расчета селективности (selectivity) предикатов.
Cardinality-Aware Index Scan
Начиная с версии 0.6.5.2, AngaraBase использует улучшенный алгоритм выбора между
IndexScan и SeqScan, учитывающий кардинальность колонок.
Ранее планировщик мог ошибочно выбирать индекс для колонок с малым количеством уникальных значений из-за жестких ограничений на минимальную селективность. Теперь это ограничение снято, и CBO корректно вычисляет стоимость для низкокардинальных колонок.
Как это работает:
- Планировщик вычисляет селективность фильтра на основе
distinct_estimate. - Если селективность превышает порог
[execution].index_cardinality_threshold(по умолчанию 0.15), планировщик предпочитаетSeqScanдля соответствующего гейта («low cardinality» вEXPLAIN; см. также порогindex_scan_selectivity_thresholdдля причины «low selectivity»). - В
EXPLAINвыводится причина выбора:seq scan chosen: low cardinality (0.1328).
Пример:
Если в таблице на 1 000 000 строк колонка status имеет всего 3 значения,
селективность фильтра status = 'ACTIVE' будет около 0.33. Поскольку 0.33 > 0.15,
база выберет последовательное сканирование, так как чтение трети таблицы через
индекс будет медленнее из-за случайного I/O.
Multicolumn Statistics
Multicolumn statistics позволяют оптимизатору учитывать корреляцию между несколькими колонками, что критично для сложных предикатов.
New in 0.6.4.18: Multicolumn statistics collected by
ANALYZEare now persisted to disk (sys_catalog snapshot protocol v4). Statistics survive server restarts. To force a fresh collection, runANALYZE <table>again.
Просмотр статистики
Статистика доступна через системные представления (sys_catalog).
Real-Time Statistics (RM-0.6.7.2)
AngaraBase поддерживает инлайн-обновление счётчиков строк непосредственно на фазе COMMIT
транзакции (без I/O overhead). При каждом COMMIT атомарно обновляется row_count_live
в памяти для всех затронутых таблиц.
Фоновый воркер (Lock-free Dirty Set)
Фоновый воркер статистики использует lock-free AtomicBool флаг (needs_histogram_recalc)
вместо очереди задач. При превышении порога staleness таблица помечается в Dirty Set.
Воркер периодически сканирует Dirty Set и запускает micro-rescan только для помеченных таблиц.
Преимущества: устранение queue congestion при массовых DML; нет блокировок при записи в dirty set.
QoS-управление фоновым воркером
Воркер статистики работает с приоритетом IoPriority::Low (BACKGROUND class).
При высокой нагрузке I/O (foreground pressure) воркер добавляет паузу 50мс
(статический backpressure). Это защищает OLTP latency от деградации при интенсивном ANALYZE.
Snapshot Age Dampening (CBO)
При использовании старого снапшота транзакции (более ANGARABASE_STATS_DRIFT_MAX_AGE_MS
миллисекунд, по умолчанию 30 сек) планировщик запросов отказывается от использования
HashJoin и переходит на spill-safe операторы. Это предотвращает OOM при устаревшей
статистике.
Диагностика: метрика angarabase_optimizer_drift_fallback_total показывает
количество случаев когда HashJoin был пропущен из-за snapshot age dampening.
Конфигурация:
| ENV knob | Default | Описание |
|---|---|---|
ANGARABASE_STATS_DRIFT_MAX_AGE_MS | 30000 | Порог возраста снапшота (мс) при котором CBO запрещает HashJoin. 0 = отключить dampening. |
AngaraStream
AngaraStream provides Change Data Capture (CDC) capabilities for AngaraBase.
start_offset semantics
The start_offset parameter controls which events are delivered to a new subscription.
| Value | Behaviour |
|---|---|
'latest' (default) | Skips historical events. Only new events published after the subscription is created are delivered. |
'earliest' | Delivers all events currently in the buffer, starting from the oldest retained event. |
Buffer overflow with earliest
If the internal event buffer has been partially evicted before 'earliest' is processed,
AngaraBase returns StreamGapError. In this case, drop the subscription and recreate it
(the gap cannot be recovered without a re-seed).
-- recreate after StreamGapError
SELECT angara_stream_unsubscribe('my-sub');
SELECT angara_stream_subscribe('my-topic', 'my-sub', start_offset => 'earliest');
Checkpoint Operations
Checkpoint — это процесс сброса грязных страниц из памяти на диск и синхронизации WAL, обеспечивающий долговечность данных и ускоряющий восстановление после сбоев.
CheckpointWorker
Процесс чекпоинта управляется фоновым воркером CheckpointWorker.
New in 0.6.4.18: CheckpointWorker has been refactored. The checkpoint logic is now consolidated in
storage::CheckpointWorkerand exposed via theCheckpointEngineOpstrait. The server-side entry point is a thin wrapper. Legacy behaviour is preserved viarun_legacy()and activated automatically for heap-primary tables.
Настройка
Параметры чекпоинта настраиваются в angarabase.toml в секции [storage.checkpoint].
Параллельный checkpoint (RM-0.6.6.8)
В версии RM-0.6.6.8 была реализована поддержка параллельного выполнения чекпоинтов для нескольких баз данных. Ранее чекпоинты выполнялись последовательно в одном цикле, что могло приводить к задержкам при большом количестве активных БД.
- Новый knob:
ANGARABASE_CHECKPOINT_MAX_PARALLEL_DBS(default: 4, range: 1-32) - Config key:
checkpoint_max_parallel_dbs - Описание: Управляет числом одновременно выполняемых per-DB чекпоинтов. Рекомендуется увеличивать при большом количестве активных баз данных (например, N_дб > 10).
- Новая метрика:
angarabase_checkpoint_parallel_dbs_active(gauge) — показывает текущее количество баз данных, для которых выполняется чекпоинт в данный момент.
Метрики overlay→heap flush (RM-0.6.6.13)
В рамках RM-0.6.6.13 добавлены метрики для отслеживания процесса материализации данных из overlay-слоев в HeapStore во время чекпоинта или корректного завершения работы (graceful shutdown).
| Метрика | Тип | Описание |
|---|---|---|
angarabase_overlay_flush_on_checkpoint_slots_total | counter | Число overlay-слотов, материализованных в heap. |
angarabase_overlay_flush_on_checkpoint_tables_total | counter | Число таблиц, для которых выполнен overlay flush. |
PromQL — интенсивность сброса overlay (слотов/сек):
rate(angarabase_overlay_flush_on_checkpoint_slots_total[5m])
PromQL — интенсивность сброса overlay (таблиц/сек):
rate(angarabase_overlay_flush_on_checkpoint_tables_total[5m])
Note: Данные метрики инкрементируются в фазе
flush_pending_overlay_to_heapпри выполнении чекпоинта и во время финального сброса данных при graceful shutdown (Phase 3.5).
Invariant Registry — руководство инженера
Canonical registry:
Lint tool:tools/lint/invariant_refs.py
Introduced: RM-0.6.4.11
AngaraBase Invariant Registry делает ключевые архитектурные гарантии машинно-трассируемыми: каждый инвариант связывает ID → RFC/spec → тесты → метрики → evidence. Это предотвращает drift между документацией, кодом и наблюдаемостью.
Текущие инварианты (seed v0)
| ID | Подсистема | Risk | Статус |
|---|---|---|---|
INV-MVCC-SNAPSHOT-VISIBILITY | tx_overlay | critical | active |
INV-WAL-DURABLE-AFTER-FSYNC | wal | critical | active |
INV-RECOVERY-REDO-UNDO-CLR | recovery | critical | active |
INV-RESOURCE-FAIL-CLOSED | storage/backpressure | high | active |
INV-SPILL-RECURSION-OVERFLOW-53400 | query/spill | high | active |
Когда обязательно указывать INV-ID в коде
При изменении файлов в следующих путях необходимо включить // INV-<ID> comment
или добавить файл в scoped allowlist:
| Путь | Обязательный инвариант |
|---|---|
crates/angarabase/src/tx_overlay/ | INV-MVCC-SNAPSHOT-VISIBILITY |
crates/angarabase/src/wal/ | INV-WAL-DURABLE-AFTER-FSYNC |
crates/angarabase/src/recovery.rs | INV-RECOVERY-REDO-UNDO-CLR |
crates/angarabase/src/storage/backpressure/ | INV-RESOURCE-FAIL-CLOSED |
crates/angarabase/src/query/spill/ | INV-SPILL-RECURSION-OVERFLOW-53400 |
Пример code comment
#![allow(unused)]
fn main() {
// INV-WAL-DURABLE-AFTER-FSYNC: UndoAppend must be WAL-durable before PageDelta is written.
// See: RFC-2026-073 §4.Y — ordering invariant (UNDO-before-heap).
assert!(
undo_lsn < page_delta_lsn,
"WAL ordering invariant violated: undo_lsn={} >= page_delta_lsn={}",
undo_lsn, page_delta_lsn
);
}
Как добавить новый инвариант
Шаг 1 — Добавить запись в invariants.yaml
- id: INV-<CATEGORY>-<NAME>
title: "Human-readable name"
surface: <module_path> # e.g. tx_overlay, wal, query/spill
risk_level: critical # critical | high | medium
owner: <team> # e.g. storage-team, query-team
spec_refs:
- rfcs/RFC-YYYY-NNN-name.md # path relative to repo root docs/rfcs/
test_refs:
- crates/angarabase/src/<path>/tests.rs
metric_refs:
- angarabase_<metric_name> # Prometheus metric name (not a file path)
evidence_refs: [] # or list of pinned evidence paths
status: active # or pending_evidence if refs TBD
Шаг 2 — Если refs ещё не реализованы
Используй status: pending_evidence и добавь target_rm:
status: pending_evidence
target_rm: RM-0.6.5.0 # train, который создаст тесты/метрики
Lint не проверяет file refs для pending_evidence инвариантов.
Шаг 3 — Проверить lint
python3 tools/lint/invariant_refs.py --check invariants.yaml
# → exit 0: OK
Шаг 4 — Добавить комментарий в код
Найди assertion/guard в исходном коде и добавь // INV-<ID> comment рядом.
Шаг 5 — Закоммитить
tools/dev/git-commit-safe.sh -m "NEW(invariants): add INV-<ID> to registry" \
-- invariants.yaml
Поля схемы
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id | string | ✓ | Уникальный ID, начинается с INV- |
title | string | ✓ | Короткое человекочитаемое название |
surface | string | ✓ | Модуль/подсистема |
risk_level | enum | ✓ | critical / high / medium |
owner | string | ✓ | Команда-owner |
spec_refs | list[path] | ✓ | Пути к RFC/spec (проверяются lint-ом) |
test_refs | list[path] | ✓ | Пути к тест-файлам (проверяются lint-ом) |
metric_refs | list[string] | ✓ | Prometheus-метрики (имена) |
evidence_refs | list[path] | ✓ | Pinned evidence (проверяются lint-ом; [] = нет) |
status | enum | ✓ | active / pending_evidence |
target_rm | string | для pending_evidence | Train, закрывающий gap |
Запуск lint в CI
Lint запускается автоматически через docs/validate-docs.sh:
bash docs/validate-docs.sh
# → ✅ Invariant registry valid (5 invariant(s) checked, 0 errors)
Standalone:
python3 tools/lint/invariant_refs.py --check invariants.yaml
# exit 0 → OK
# exit 1 → broken ref или schema error (блокирует CI)
Связанные документы
Project Health Dashboard
Project Health Dashboard нужен Tech Lead для контроля здоровья проекта как продукта и репозитория. Это отдельный контур от runtime/DBA observability: здесь анализируются train, риски, tech debt, LOC и quality gates.
Для чего использовать
- Быстро понять, какой train активен и какой был закрыт последним.
- Увидеть проблемные зоны: активные Red/Amber риски и открытый High/Critical debt.
- Найти самые большие файлы (top-10 LOC) и риск по
src_loc_guard. - Проверить статус quality gates по evidence, без ручного обхода логов.
- Оценить архитектурную дисциплину через invariant-сигналы.
Источник данных
Метрики генерируются скриптом:
python3 tools/observability/export_metrics.py --format prometheus --out artifacts/tmp/project_health.prom
Ключевые источники:
-
PROJECT_STATUS.md -
latest gate artifacts в
docs/planning/evidence/release_trains/<RM-ID>/(если есть)
Метрики и смысл
angara_project_release_health— release контекст (active/closed/planning).angara_project_active_risks— количество активных рисков.angara_project_tech_debt_by_component— debt по компонентам/серьёзности.angara_project_top_loc_files— top LOC + маркеры порогов.angara_project_gate_status— PASS/FAIL/unknown quality gates.angara_project_architecture_health— invariants total + missing links.
Grafana dashboard
- Title:
AngaraBase Project Health - UID:
angarabase-project-health-v0 - Path:
tools/observability/grafana/angarabase-project-health.json
Dashboard intentionally не содержит runtime-панелей (QueryStore/pgwire/io_uring/WAL runtime): это уровень project governance.
Architecture Overview
Этот документ — карта архитектуры AngaraBase as-is: какие крупные подсистемы существуют, как по ним течёт SQL-запрос и где лежат границы ответственности. Для пользовательского введения см. Архитектура AngaraBase.
Высокоуровневые компоненты
| Компонент | Что делает |
|---|---|
angarabased | Серверный адаптер: pgwire-протокол, listener, управление соединениями и сессиями |
angarabase (engine core) | Parse/bind/plan/execute, транзакции, storage API, WAL/recovery primitives |
angara-cli | CLI для администрирования (identity, ops через admin endpoint) |
| Operational surface | Конфигурация, метрики, логи, диагностические bundle, политики upgrade |
Полный layering-контракт и правила зависимостей: Layering and Boundaries.
Поток запроса (упрощённо)
flowchart LR
C[Client/Driver] -- pgwire --> S[angarabased adapter]
S -- SQL + session ctx --> E[angarabase engine core]
E --> P[Parse / Bind / Plan / Execute]
P --> Sec[Security: RBAC + RLS]
P --> T[Txn / MVCC]
P --> St[Storage API]
P --> Stat[Stats / CBO feedback]
T --> Wal[WAL / Recovery]
St --> Wal
Wal --> IO[IO / fsync contract]
E -- rows / errors --> S
S -- pgwire responses --> C
Ключевые архитектурные решения
| Область | Решение | Почему |
|---|---|---|
| MVCC | UNDO-log (история — отдельный append-only log; heap содержит только текущие версии) | Меньше bloat, нет тяжёлого VACUUM, детерминированный GC |
| Storage | Pluggable: row-store baseline + AngaraMemory; AngaraColumn в roadmap | HTAP-направление, разные tier’ы для разных нагрузок |
| Recovery | WAL-first, идемпотентный replay, fail-closed при отсутствии WAL целостности | Корректность важнее latency |
| Optimizer | Cost-based AngaraPlan + LEO feedback loop, robust planning | Устойчивость к ошибкам оценок |
| Execution | Volcano streaming (AngaraFlow) + vector path (AngaraVector) | Разделение по плановым формам, явное управление через EXPLAIN |
| Catalog | Persisted SysCatalog, DDL переживает restart | Предсказуемость для production |
| Security | 6-слойная модель: TLS/Auth → RBAC → RLS → Break-glass → Audit chain → TDE | Defence-in-depth, fail-closed |
| Backup | Per-database, cold + online/PITR baseline | Multi-tenant изоляция |
| Distribution | Single-node engine; distributed SQL — горизонт major-веток | Concentration on correctness first |
Границы и инварианты
angarabased(адаптер) не содержит SQL-логики — только pgwire framing, session ctx, маршрутизация в core.angarabasecore не знает о pgwire — общается через core API контракт.- Storage не делает MVCC visibility — только heap I/O. Visibility вычисляет MVCC layer.
- Index не определяет видимость — только указывает на TID; visibility всегда recheck по heap.
- Любая неподдерживаемая SQL-конструкция возвращает явный SQLSTATE (
0A000и др.) — никаких silent bypass. - Public API: pgwire + admin endpoint. Внутренние модули — implementation detail и могут меняться.
Архитектурные ограничения и do-not-block правила: Architecture Constraints.
Надёжность и физическая переносимость
- Cold/offline backup и restore — full-instance copy на уровне data-directory (см. Backup/Restore).
- Host migration — без
pg_dump/pg_restore: copy + verify + start. Подробнее в Crash recovery. - Identity rehearsal — каждый release проходит rehearsal upgrade pipeline.
- Page checksums + WAL CRC — обнаружение corruption на чтении/восстановлении.
Дополнительные материалы
- Layering and Boundaries — официальный layering-контракт.
- Архитектура AngaraBase (user-facing) — обзор для пользователей и DBA.
- Project principles — идеологический компас проекта.
Table Partitioning
AngaraBase поддерживает декларативное партицирование (RFC-2026-097 v1): RANGE и LIST стратегии с DEFAULT catch-all.
Поддерживаемые стратегии
| Стратегия | Синтаксис | Когда использовать |
|---|---|---|
| RANGE | PARTITION BY RANGE (col) | Временны́е ряды, диапазоны ID |
| LIST | PARTITION BY LIST (col) | Категориальные значения (регион, тип) |
| DEFAULT | PARTITION OF parent DEFAULT | Catch-all для строк вне всех диапазонов |
DDL
Создание партицированной таблицы
Для создания партицированной таблицы используется предложение PARTITION BY.
CREATE TABLE orders (
id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
amount_usd BIGINT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
month_ts BIGINT NOT NULL,
CONSTRAINT orders_pkey PRIMARY KEY (id, month_ts)
) PARTITION BY RANGE (month_ts);
Прикрепление дочерней секции
Дочерние секции (партиции) создаются с указанием родительской таблицы и диапазона значений (для RANGE) или списка значений (для LIST).
-- RANGE партиция для января 2025
CREATE TABLE orders_p2025_01 PARTITION OF orders
FOR VALUES FROM (1735689600) TO (1738368000);
-- RANGE партиция для февраля 2025
CREATE TABLE orders_p2025_02 PARTITION OF orders
FOR VALUES FROM (1738368000) TO (1740787200);
-- DEFAULT партиция (catch-all)
CREATE TABLE orders_p_default PARTITION OF orders DEFAULT;
DML через parent
INSERT
INSERT в parent автоматически маршрутизируется в подходящую child partition по значению partition key.
-- Строка попадёт в соответствующую month-partition
INSERT INTO orders (id, user_id, amount_usd, month_ts)
VALUES (1, 42, 9900, 1735689601);
Ошибка при отсутствии совпадения: если строка не входит ни в один диапазон и нет DEFAULT partition — SQLSTATE 23514 check_violation.
Ограничение ON CONFLICT: ON CONFLICT не поддерживается на partitioned parent — вернёт ошибку feature_not_supported (SQLSTATE 0A000).
SELECT через parent (UNION ALL expansion + pruning)
SELECT из parent автоматически разворачивается в UNION ALL по всем children. Если WHERE содержит условие на partition key — нерелевантные partitions пропускаются (pruning).
-- Сканирует только partition для January 2025
SELECT * FROM orders WHERE month_ts >= 1735689600 AND month_ts < 1738368000;
UPDATE через parent
UPDATE по non-partition key столбцам работает через fan-out на все (или pruned) children.
UPDATE orders SET status = 'shipped' WHERE id = 42 AND month_ts = 1735689601;
Ограничение: UPDATE partition key column запрещён — вернёт SQLSTATE 23514. Cross-partition row movement не поддерживается в v1.
DELETE через parent
DELETE с WHERE на partition key применяет pruning и удаляет только из matching children.
DELETE FROM orders WHERE month_ts = 1735689601 AND id = 42;
Мониторинг
| Метрика | Описание |
|---|---|
angarabase_partition_route_ok_total | Успешных INSERT routing в child |
angarabase_partition_route_no_match_total | INSERT без matching partition (→ 23514) |
angarabase_partition_route_default_total | INSERT в DEFAULT partition |
angarabase_partition_pruned_branches_total | Children пропущено при SELECT/DML |
Ограничения v1
- Hash partitioning — не поддерживается (planned v0.7)
- Subpartitioning / multi-column partition key — не поддерживается (v0.7)
- Cross-partition UPDATE — запрещён (явная ошибка 23514)
- ON CONFLICT на parent table — не поддерживается
- REINDEX через parent — не поддерживается
Troubleshooting
| Симптом | Причина | Решение |
|---|---|---|
ERROR 23514 check_violation при INSERT | Значение partition key не попадает ни в один диапазон | Добавить DEFAULT partition или проверить значение |
ERROR 23514 при UPDATE | Попытка изменить partition key column | Не изменяй partition key; DELETE + INSERT вместо UPDATE |
ERROR 0A000 ON CONFLICT not supported | ON CONFLICT через parent partition | Выполняй INSERT напрямую в child partition |
Index Durability
Overview
AngaraBase ensures that all indexes, including PRIMARY KEY and secondary BTree indexes, are persistent and survive system restarts or crashes. Indexes are managed by the IndexStore component, which handles the allocation of unique table identifiers (index_table_id) and coordinates with the Checkpoint worker to flush index pages to persistent storage.
There is one deliberate exception: indexes over volatile InMemory tables (storage='memory', durability='none'),
including CREATE TEMP TABLE, are catalog-visible for the session/query planner but do not allocate a persistent
index_table_id. They are rebuilt from the live in-memory heap when needed and disappear with the table.
Durability pipeline (PRIMARY KEY)
The durability of PRIMARY KEY indexes is guaranteed through a multi-stage process that integrates with the system catalog and the checkpointing mechanism:
- Table Creation: When a
CREATE TABLE ... PRIMARY KEYstatement is executed, the DDL executor allocates a uniqueindex_table_idusing the storage engine. - Catalog Persistence: The Primary Key definition is saved in the
SysCatalogwith its assignedindex_table_id. This ensures that the mapping between the table and its index is persistent. - Checkpoint Integration: The Checkpoint worker periodically calls
flush_all_indexes(). This operation forces all dirty index pages from memory to disk. - Recovery and Restoration: Upon system restart, the recovery process reads the index definitions from the catalog and restores the index state from the persisted pages on disk.
- Startup Backfill (Legacy Migration): For legacy databases where PRIMARY KEY indexes were created without an
index_table_id, AngaraBase performs an asynchronous background backfill after the database begins accepting connections (to avoid blocking startup). This process identifies legacy PKs, allocates the missingindex_table_id, updates the catalog, and persists the index pages.
Durability pipeline (secondary indexes)
Secondary indexes follow a “durable-by-default” path during creation and maintenance:
- Immediate Persistence: During
CREATE INDEX, the system immediately forces a synchronous flush of index pages to disk after the index build is complete. This ensures that the index is durable even if a crash occurs before the next checkpoint. - Periodic Flushing: Similar to Primary Keys, secondary indexes are included in the periodic
flush_all_indexes()calls by the Checkpoint worker.
Volatile InMemory indexes
InMemory tables with durability='none' use a volatile index path. This includes temporary tables, because
CREATE TEMP TABLE is forced to memory + durability=none even if the statement includes a durable storage hint.
Behavior:
CREATE INDEXsucceeds on volatile InMemory tables.- The index definition is visible in the catalog while the table exists.
index_table_idis intentionally absent, because there are no persistent index pages to restore.- The executor can still use a B-Tree/index-scan path by building an ephemeral index from current in-memory rows.
- On session disconnect or temp table cleanup, the table and its volatile index metadata are removed together.
Example:
SET search_path = public;
CREATE TEMP TABLE tt_items (
id INT,
code mvarchar(16)
);
INSERT INTO tt_items (id, code) VALUES (1, 'AbC ');
CREATE INDEX idx_tt_items_code ON tt_items (code);
-- Uses mvarchar equality semantics and can be served through the volatile index path.
SELECT id FROM tt_items WHERE code = 'abc';
This design keeps temp-table workloads fast and avoids WAL/checkpoint pressure, while preserving the same
comparison contract as durable B-Tree indexes. In particular, mvarchar index keys are normalized with the same
case-insensitive and trailing-space-insensitive rules used by expression evaluation.
Checkpoint fail-closed semantics
AngaraBase employs a fail-closed approach to index durability during the checkpoint process. The flush_all_indexes() operation returns a success status:
- Success: If all indexes are successfully flushed, the checkpoint continues, and the
end_checkpointrecord is written to the WAL. - Failure: If
flush_all_indexes()returnsfalse(indicating a flush error), the checkpoint is aborted. Theend_checkpointrecord is not written.
In the event of an aborted checkpoint, the next system startup will trigger a WAL replay starting from the last successfully completed checkpoint, ensuring that no index data is lost or left in an inconsistent state. The metric angarabase_checkpoint_index_flush_errors_total tracks these occurrences.
Monitoring
You can monitor the status of index durability and backfill operations using the following Prometheus metrics:
| Metric | Type | Description |
|---|---|---|
angarabase_pkey_backfill_in_progress | Gauge | 1 while startup PK backfill is running |
angarabase_pkey_backfill_ok_total | Counter | PK indexes successfully backfilled with TableId |
angarabase_pkey_backfill_fail_total | Counter | PK backfill failures (allocation or persist error) |
angarabase_checkpoint_index_flush_errors_total | Counter | Checkpoint aborted due to index flush failure |
angarabase_index_pkey_no_table_id_total | Gauge | Legacy PK indexes found at startup (before backfill) |
angarabase_index_restore_empty_total | Counter | Indexes that restored empty after restart (Alert if > 0) |
angarabase_wal_lsn_drift_resets_total | Counter | WAL VLF LSN drift resets after crash (Alert if > 0) |
angarabase_index_stale_tuple_fallbacks_total | Counter | UPDATE fallbacks to seq-scan due to stale index tuple |
Alerting Guidance & PromQL
- Empty Indexes:
rate(angarabase_index_restore_empty_total[5m]) > 0- Threshold: > 0 is critical. Indicates data loss or corruption in index persistence.
- WAL Drift:
rate(angarabase_wal_lsn_drift_resets_total[5m]) > 0- Threshold: > 0 is critical. Indicates WAL corruption or crash-safety failure.
- Stale Tuples:
rate(angarabase_index_stale_tuple_fallbacks_total[5m]) > 0.1- Threshold: Occasional fallbacks are normal, but a high rate indicates index corruption or MVCC issues.
Troubleshooting
“После рестарта индекс пустой (entries=0)”
If an index appears empty after a restart despite having data previously (or if angarabase_index_restore_empty_total > 0), check the following:
- Legacy PKs: Check
angarabase_index_pkey_no_table_id_total. If it is greater than 0, the backfill might still be in progress (wait for completion) or have failed (check logs for allocation errors). - Checkpoint Failures: Verify if
angarabase_checkpoint_index_flush_errors_totalis incrementing. A failure to flush indexes prevents the checkpoint from completing. Check disk space and permissions. - Logs: Inspect system logs for
WAL replayerrors or messages indicating that index pages could not be restored.
“Checkpoint loop не завершается”
If the checkpoint process seems stuck or keeps restarting:
- Flush Errors: Check the
angarabase_checkpoint_index_flush_errors_totalmetric. - Worker Logs: Look for
checkpoint_worker: flush_all_indexes failedin the logs. This indicates that the index store is unable to persist pages, possibly due to disk space issues or I/O errors.
“WAL LSN drift resets > 0”
If angarabase_wal_lsn_drift_resets_total is incrementing:
- This indicates that after a crash (e.g.,
kill -9), the WAL head LSN was out of sync with the actual physical WAL size, and the system had to reset it. - Check the logs for
append_commit FAILEDorWAL VLF LSN driftmessages. While the system recovers automatically, frequent occurrences might indicate underlying storage fsync issues.
“High rate of stale tuple fallbacks”
If angarabase_index_stale_tuple_fallbacks_total is spiking:
- This means UPDATE operations are finding index entries that point to non-existent or stale tuples, forcing a slow sequential scan fallback.
- This can happen during heavy concurrent UPDATEs. If it persists, consider REINDEXing the affected table.
SQL examples
-- Verify index usage and check for stale index fallbacks
EXPLAIN SELECT * FROM public.your_table WHERE id = 123;
-- If the query plan shows [stale_index], it means the index entry was stale
-- and the engine fell back to a sequential scan.
NOTE: System catalog tables for index metadata (
angara_sys.indexesandangara_sys.index_stats) are not part of the current user-facing SQL surface. UseEXPLAINto verify index usage.
Слои архитектуры и governance зависимостей
Модель слоёв стабилизирована (active). Изменения вносятся только через RFC.
Цель: иметь простую, проверяемую модель слоёв и зависимостей, чтобы изменения не размывали границы.
Слои (рабочая модель)
- Core engine (
angarabase): семантика SQL, транзакции, storage API, WAL/recovery primitives. - Adapters (
angarabased, будущие): pgwire/HTTP/admin surfaces, преобразование протоколов. - Tooling (
angara-cli,tools/*): утилиты, runners, тестовые harness’ы. - Distribution/Packaging tooling (
packaging/*,tools/release/*): release artifacts, signatures, package manifests, publication scripts. - Operational surfaces: конфигурация, runbooks, policies, evidence packs.
Правило зависимостей (самое важное)
- Core не зависит от adapters и tooling.
- Adapters могут зависеть от core.
- Tooling может зависеть от core и adapters (но без обратных крючков в core).
- Distribution/Packaging tooling может зависеть от tooling/core artifacts и не вносит runtime dependency в core/adapters.
Визуальная схема
flowchart TB
subgraph Core[Core engine (angarabase)]
CoreAPI[engine public API]
end
subgraph Adapters[Adapters (angarabased, pgwire, ...)]
Pgwire[pgwire]
Admin[admin surfaces]
end
subgraph Tooling[Tooling (angara-cli, tools/*)]
CLI[angara-cli]
Runners[test/bench runners]
end
Adapters --> Core
Tooling --> Core
Tooling --> Adapters
CoreAPI --> Core
Связанные документы
- Do-not-block constraints:
angarabook/src/architecture/constraints.md - Engine core карта:
angarabook/src/architecture/components/engine_core.md - Governance RFC:
RFC-2026-449-architecture-layering-and-dependency-governance-v0
Known issues (testing)
Это user-facing “выжимка”. Каноничный список: angarabook/src/operations/known-issues.md.
SQLSTATE quick reference
| SQLSTATE | Name | Context |
|---|---|---|
0A000 | feature_not_supported | Unsupported SQL forms, complex RLS predicates in IR mode, server-side predicates on client-encrypted columns (randomized), unsupported RLS mask expressions |
22023 | invalid_parameter_value | Invalid stats_level_max values, invalid SET BREAK_GLASS ... TTL=... values |
23514 | check_violation | Insert into partitioned parent with no matching child/DEFAULT partition |
25001 | active_sql_transaction | SET SESSION CONTEXT inside an active transaction |
42501 | insufficient_privilege | User/role/policy/break-glass actions without required roles, protected SQL without SecurityContext |
42809 | wrong_object_type | DML on append-only tables, disabling append-only on child while parent is append-only |
General
pg_database probe (KI-2026-001)
Некоторые pg_database запросы могут приводить к stall/hang.
См. детали и repro: angarabook/src/operations/known-issues.md → KI-2026-001.
Checksum verification
- If on-disk page verification fails, read path fails closed with explicit
checksum mismatchdiagnostics. - Quick operator probe:
angara-cli storage verify-pages --dir <data_dir> --json
SQL behavior
Unsupported SQL forms
0A000 feature_not_supported is expected for currently out-of-scope SQL forms:
WITH RECURSIVE- Set operations (
UNION/INTERSECT/EXCEPT) - Window functions
ORDER BY ... NULLS FIRST|LAST
Partitioning
23514 check_violation is expected when inserting into a partitioned parent table and no child partition (and
no DEFAULT partition) matches the row partition key.
Append-only tables
42809 wrong_object_type is expected for:
UPDATEon an append-only table,DELETEon an append-only table,- Attached child partition trying to disable append-only while parent remains append-only.
Stats parameter validation
22023 invalid_parameter_value is expected for invalid stats_level_max values outside [0..3].
Statistics
HLL NDV tracking
HLL NDV tracking for TEXT columns skips very long values (len > 256) by design.
This keeps memory and merge cost bounded for streaming stats.
Security behavior
Privilege enforcement
42501 insufficient_privilegeis expected when user/role/policy/break-glass actions are executed without required roles.22023 invalid_parameter_valueis expected for invalidSET BREAK_GLASS ... TTL=...values (missing/zero/exceeds max TTL).25001 active_sql_transactionis expected forSET SESSION CONTEXTinside an active transaction.
Session security context
42501 insufficient_privilegeis expected inscram/certmodes when protected SQL executes without a sessionSecurityContext.0A000 feature_not_supportedis expected in IR mode for unsupported complex RLS predicates (bounded fail-closed planner/IR contract).
Client encryption and RLS masks
0A000 feature_not_supportedis expected for unsupported server-side predicates on client-encrypted columns in randomized mode.0A000 feature_not_supportedis expected for unsupported RLS mask expressions outside v1 bounded forms (partial,nullify).
Дальше
- Поддержка и сбор артефактов баг-репорта — как сообщить о новой проблеме, если своей в списке нет.
- Совместимость клиентов — какие клиенты протестированы как «works as documented».
- Обзор совместимости SQL — какие SQL-конструкции возвращают
0A000и почему.
Глоссарий
Единый справочник терминов AngaraBase. Термины расположены в алфавитном порядке (латиница, затем кириллица).
B
AngaraAdapt — подсистема адаптивной обработки запросов (v5). Автоматическая коррекция планов на основе runtime feedback: если фактическая кардинальность значительно отличается от оценки, план пересчитывается на лету.
AngaraFlow — подсистема потокового исполнения запросов. Реализует Volcano-модель (iterator model) с операторами scan, filter, join, sort, aggregate. Каждый оператор запрашивает следующую порцию данных у дочернего оператора.
AngaraGC — подсистема сборки мусора MVCC. Использует epoch-based watermark для определения безопасной границы очистки. Удаляет версии строк, невидимые ни одной активной транзакции.
AngaraIO — подсистема асинхронного I/O. Использует io_uring для операций со storage и WAL, минимизируя системные вызовы и переключения контекста.
AngaraMemory — in-memory storage engine (v5). Поддерживает три режима работы: volatile (данные только в памяти), logged (с записью в WAL), snapshotted (с периодическими снимками на диск).
AngaraNet — подсистема сетевого I/O на базе io_uring (v5). Обеспечивает асинхронную обработку сетевых операций без блокировки потоков.
AngaraParallel — подсистема параллельного исполнения запросов (v5). Morsel-driven модель с work-stealing
scheduler для утилизации многоядерных процессоров. NUMA-aware распределение (per-node morsel queues, thread
pinning) отложено в v0.7 (RFC-2026-376 §13 H2 — «NUMA-aware shard selection»); до этого исполнение
NUMA-agnostic, EXPLAIN репортит numa_affinity=disabled.
AngaraPlan — cost-based оптимизатор запросов. Использует robust planning (устойчивость к ошибкам оценок) и LEO feedback (обучение на фактических метриках выполнения).
AngaraPool — подсистема управления соединениями и потоками. Отвечает за connection pooling, thread scheduling и распределение ресурсов между сессиями.
AngaraStat — подсистема сбора статистики для оптимизатора. Включает HyperLogLog для NDV, equi-height гистограммы, MCV (Most Common Values) и reservoir sampling для построения выборок.
AngaraTree — индексный движок. Поддерживает B+tree (основной тип индекса), BRIN (Block Range Index для append-only данных) и Hash (для точечных поисков по равенству).
AngaraVector — подсистема векторизованного исполнения (v5). Обрабатывает данные пакетами (batches) с использованием SIMD-инструкций: AVX2, AVX-512 на x86-64 и NEON на ARM.
BRIN (Block Range Index) — легковесный индекс, хранящий min/max значения для диапазонов страниц. Эффективен для append-only и time-series данных, где значения естественно упорядочены.
Break-glass — механизм контролируемого повышения привилегий. Позволяет авторизованным пользователям временно получить расширенные права с обязательным указанием причины, ограниченным TTL и полным аудитом всех действий.
C
CBO (Cost-Based Optimizer) — оптимизатор запросов, выбирающий план выполнения на основе статистики (кардинальность, NDV, гистограммы) и моделей стоимости (CPU, I/O, memory).
E
Epoch — логическая единица времени в подсистеме MVCC. Каждый успешный commit увеличивает глобальный epoch. Epoch используется для определения видимости версий строк и вычисления GC watermark.
F
Fail-closed — принцип безопасности, при котором система в случае неопределённости отклоняет операцию, а не пропускает. Например, если RLS-политику невозможно вычислить, доступ запрещается.
G
GC watermark — минимальный snapshot среди всех активных транзакций. Определяет безопасную границу для
сборки мусора: версии строк с deleted_commit < watermark могут быть удалены.
H
HLL (HyperLogLog) — вероятностная структура данных для приблизительного подсчёта уникальных значений (NDV). Использует фиксированный объём памяти (~1 КБ) независимо от количества значений. Относительная погрешность ~2%.
L
LEO (Learning Optimizer) — компонент AngaraPlan, корректирующий модели стоимости на основе фактических метрик выполнения запросов. После каждого выполнения сравнивает оценочную и реальную кардинальность и обновляет поправочные коэффициенты.
LSN (Log Sequence Number) — монотонно растущий идентификатор записи в WAL. Используется для определения порядка записей, позиции восстановления и репликации.
M
MCV (Most Common Values) — список наиболее часто встречающихся значений колонки вместе с их частотами. Используется оптимизатором для точной оценки кардинальности при фильтрации по конкретным значениям.
MVCC (Multi-Version Concurrency Control) — механизм конкурентного доступа к данным через версионирование строк. Позволяет читателям и писателям работать одновременно без взаимных блокировок. Каждая модификация создаёт новую версию строки, а не изменяет существующую.
N
NDV (Number of Distinct Values) — количество уникальных значений в колонке. Ключевая метрика для оптимизатора: влияет на оценку кардинальности joins и group by.
P
pgwire — PostgreSQL wire protocol. Сетевой протокол, используемый AngaraBase для взаимодействия с клиентами. Обеспечивает совместимость с PostgreSQL-клиентами (psql, драйверы libpq, JDBC).
PITR (Point-In-Time Recovery) — механизм восстановления базы данных на произвольный момент времени. Использует базовый backup + воспроизведение WAL-записей до указанного LSN или timestamp.
R
RBAC (Role-Based Access Control) — модель управления доступом на основе ролей. Привилегии назначаются ролям, роли — пользователям. Поддерживает вложенные роли и наследование привилегий.
RLS (Row-Level Security) — механизм политик видимости строк на уровне таблицы. Позволяет ограничить доступ к отдельным строкам на основе атрибутов текущего пользователя (роль, department, tenant_id).
S
SQLSTATE — 5-символьный код ошибки по стандарту SQL (ISO/IEC 9075). AngaraBase использует явные SQLSTATE для всех ожидаемых ошибок, что упрощает обработку ошибок в клиентских приложениях.
SysCatalog — системный каталог, центральный реестр метаданных всех объектов базы данных: таблиц, колонок, индексов, пользователей, ролей, привилегий, политик безопасности и статистики.
T
TDE (Transparent Data Encryption) — прозрачное шифрование данных на диске. Шифруются страницы данных, записи WAL и журнал аудита. Прозрачно для приложений — шифрование и дешифровка происходят на уровне storage engine.
TID (Tuple Identifier) — физический адрес строки в хранилище, состоящий из двух компонентов: (page_id, slot_id). Используется для прямого доступа к строке через индекс.
W
WAL (Write-Ahead Log) — журнал транзакций, обеспечивающий durability и recovery. Все изменения сначала записываются в WAL, затем применяются к страницам данных. При восстановлении после сбоя WAL используется для повторного применения зафиксированных, но не записанных на диск изменений.
Дальше
- Что такое AngaraBase — продуктовый обзор для тех, кто только пришёл в глоссарий из поиска.
- Архитектура AngaraBase — как именованные подсистемы (AngaraTree, AngaraPlan и др.) собираются в работающий движок.
- Системные представления
sys.*— где те же термины видны из SQL.
Системные таблицы (System Catalog)
Goal: Описание структуры и назначения системных таблиц AngaraBase для мониторинга, диагностики и управления метаданными.
Системный каталог AngaraBase доступен через виртуальную схему sys. Эти таблицы предоставляют информацию о
состоянии инстанса, конфигурации и объектах базы данных в реальном времени.
Таблица sys.tables
Содержит метаданные всех таблиц во всех базах данных и схемах.
| Поле | Тип | Описание |
|---|---|---|
db_id | string | Идентификатор базы данных. |
schema_name | string | Имя схемы (обычно public). |
table_name | string | Имя таблицы. |
tablespace_name | string | Имя табличного пространства. |
storage_engine | string | Тип движка хранения: row_store (HeapFile), memory (In-memory), htap_row_column. |
durability | string | Уровень долговечности (для memory-таблиц): none, logged, snapshotted. |
max_rows | uint64 | Лимит строк (для memory-таблиц). |
eviction_policy | string | Политика вытеснения (для memory-таблиц): error, fifo, lru, lfu. |
checkpoint_interval_ms | uint64 | Интервал чекпоинтов в мс (для snapshotted). |
current_rows | uint64 | Текущее количество живых строк (приблизительно). |
evictions_total | uint64 | Счетчик вытесненных строк. |
limit_errors_total | uint64 | Счетчик ошибок превышения лимита строк. |
append_only | bool | Флаг режима append-only (устаревший, см. mutation_policy). |
mutation_policy | string | Политика изменений: unrestricted, no_delete, append_only. |
Примечание по Storage Engine
- row_store: Стандартное хранение на диске (HeapFile).
- memory: Данные хранятся в оперативной памяти. Долговечность регулируется параметром
durability.
Таблица sys.settings
Предоставляет доступ к текущим настройкам конфигурации сервера (Effective Configuration).
| Поле | Тип | Описание |
|---|---|---|
name | string | Имя параметра (например, server.addr). |
value | string | Текущее эффективное значение. |
source | string | Источник значения: default, config, bootstrap_env, sql_runtime. |
dynamic | bool | true, если параметр можно изменить без перезагрузки. |
doc | string | Краткое описание параметра. |
Таблица sys.databases
Список доступных баз данных.
| Поле | Тип | Описание |
|---|---|---|
db_id | string | Уникальный идентификатор базы данных. |
name | string | Имя базы данных. |
Таблица sys.schemas
Список схем в базах данных.
| Поле | Тип | Описание |
|---|---|---|
db_id | string | Идентификатор базы данных. |
schema_name | string | Имя схемы. |
Troubleshooting
-
Симптом: Таблица
sys.tablesвозвращает пустой результат. -
Причина: У пользователя нет прав на просмотр метаданных или не выбрана база данных (если используется фильтрация).
-
Решение: Проверьте права доступа (RBAC).
-
Симптом: Изменение в
sys.settingsне применяется. -
Причина: Параметр имеет
dynamic = falseили перекрыт переменной окружения (source = bootstrap_env). -
Решение: Требуется перезагрузка сервера или изменение конфигурации/переменных окружения.
Links
Client Compatibility
This guide covers compatibility considerations and configuration steps for connecting various database clients to AngaraBase.
DBeaver
DBeaver is a popular database administration tool that can connect to AngaraBase via the PostgreSQL protocol.
However, DBeaver automatically sends metadata queries to pg_catalog and information_schema tables that
AngaraBase does not support, which can cause connection failures.
Problem
When connecting DBeaver to AngaraBase, you may encounter feature_not_supported errors. This happens because
DBeaver automatically sends queries to PostgreSQL system catalogs (pg_catalog.* and information_schema.*)
during connection setup and schema browsing. AngaraBase does not implement these PostgreSQL-specific metadata
tables.
Solution
Follow these steps to configure DBeaver for AngaraBase compatibility:
1. Connection Properties
In DBeaver, edit your connection and go to Driver Properties:
- Set
assumeMinServerVersion=9.0 - Set
preferQueryMode=simple
These settings reduce the number of metadata queries DBeaver sends.
2. PostgreSQL Connection Settings
In the PostgreSQL tab of your connection settings:
- Uncheck “Read all data types”
- Uncheck “Show non-default schemas”
This prevents DBeaver from querying system catalogs for type and schema information.
3. Server Type Selection
When creating the connection, select PostgreSQL 9.x as the server type. This uses a compatibility mode with minimal system catalog queries.
Diagnostics
If you’re still experiencing issues, you can enable slow query logging to see exactly what queries DBeaver is sending:
export ANGARABASE_LOG_MIN_DURATION_MS=0
export ANGARABASE_LOG_QUERY_TEXT=1
Start your AngaraBase server with these environment variables to log all queries. Check the logs to identify which specific queries are failing.
Alternative Approach
If the above configuration doesn’t work for your use case, consider using a simpler PostgreSQL client like
psql for command-line access:
psql -h localhost -p 5152 -U your_username -d your_database
Limitations
Even with proper configuration, some DBeaver features may not work with AngaraBase:
- Schema browser may show limited information
- Auto-completion may be reduced
- Some administrative features will not be available
For the most complete AngaraBase experience, consider using the native angara-cli tool or connecting via
standard PostgreSQL drivers in your applications.
Other Clients
psql
The PostgreSQL command-line client works well with AngaraBase:
psql -h localhost -p 5152 -U username -d database_name
JDBC/ODBC Drivers
Standard PostgreSQL JDBC and ODBC drivers should work with AngaraBase for basic SQL operations. Avoid using driver features that query system catalogs.
Application Frameworks
Most application frameworks (Django, Rails, etc.) work with AngaraBase when configured to use PostgreSQL drivers, though some ORM introspection features may be limited.
Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
feature_not_supported on connection | Client querying pg_catalog | Configure client to minimize metadata queries |
| Slow connection setup | Too many system queries | Use preferQueryMode=simple |
| Missing schema information | AngaraBase doesn’t implement full pg_catalog | Use direct SQL queries instead of client introspection |
Getting Help
If you encounter client compatibility issues not covered here:
- Check the Known Issues page
- Enable query logging to identify problematic queries
- Consult the Support page for additional resources
For additional client-specific configuration tips, see our community documentation.
Дальше
- Quickstart — пример коннекта
psqlс pgwire-параметрами. - Обзор совместимости SQL — что именно поддерживает SQL-уровень.
- Известные ограничения и SQLSTATE — какие коды клиент должен ожидать вместо «магии».
- Поддержка и сбор артефактов баг-репорта — если ваш клиент-драйвер ведёт себя не так, как описано.
Support / bug reports (testing)
What to include in a report
Every report should contain the following:
- Version: git commit hash (или tag), OS/kernel.
- Launch config: конфиг (
angarabase.conf) и команда запуска. - Reproduction steps: SQL/шаги/клиент (psql/ORM/tool).
- Expected vs actual behavior: что ожидалось и что произошло.
- Artifacts:
- Логи сервера.
- Если это crash/recovery/backup тема:
summary.jsonи папкуartifacts/целиком.
Helpful tooling (already in repo)
Nightly-style evidence pack
Запуск локальной evidence-пачки (один прогон):
tools/ci/nightly_gate.sh --runs 1 --root artifacts/nightly_local
Diagnostics bundle
Сбор диагностического бандла:
tools/diagnostics_bundle/run.sh --root artifacts/diagnostics_bundle
Specific scenarios
Hang / stall
Если проблема — зависание или stall:
- Приложите client-side timeout/hang описание.
- Приложите логи сервера.
- Приложите stack trace или diag bundle (если возможно).
- Проверьте known issues — в частности
KI-2026-001(pg_database probe stall).
Crash / recovery
- Приложите
summary.jsonизartifacts/. - Приложите полный каталог
artifacts/. - Укажите, было ли это при обычном запуске, при restart или при backup/restore.
Unexpected SQLSTATE
- Укажите полный текст ошибки (SQLSTATE код + message).
- Проверьте known issues — многие SQLSTATE коды документированы как ожидаемое поведение.
Дальше
- Известные ограничения и SQLSTATE — проверьте, не описана ли ваша проблема как известное ограничение.
- Совместимость клиентов — если проблема в драйвере или клиенте.
- Диагностика — как собрать
EXPLAIN, slow-log,sys.*-снимок для прикрепления к issue.
Generated Reference Artifacts
Сюда складываются автогенерируемые markdown-артефакты документации.
AngaraBook changelog (user/testing highlights)
Это не копия CHANGELOG.md и не замена release notes в planning пакетах.
Цель: дать тестерам короткий “что поменялось в опыте тестирования” + ссылки на каноничные источники.
Source of truth
-
Product changelog (executive):
CHANGELOG.md(+CHANGELOG.ru.md) -
Release trains / gates:
docs/planning/releases/v2/minor/README.md -
Known issues (canonical):
angarabook/src/operations/known-issues.md
Unreleased (testing focus)
- RM-0.6.3.4 (in_review) — CBO P4.1 remediation:
- train:
docs/planning/v0.6/RM-0.6.3.4.md - highlights: optimizer planning timeout contract hardened (
sql.optimizer.planning_timeout_ms/ANGARABASE_OPTIMIZER_PLANNING_TIMEOUT_MS), timeout path degrades to greedy planning, and optimizer observability expanded with planning counters/histogram.
- train:
- RM-5.17 (closed) — SQL Coverage Expansion:
- train:
docs/planning/releases/v5/minor/RM-5.17.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: Window functions v0 (
ROW_NUMBER,RANK,LAG,LEAD,SUM/COUNTOVER), Set operations (UNION,INTERSECT,EXCEPT), TPC-H partial benchmarks, pgbench read-write support.
- train:
- RM-5.16 (closed) — Columnar Segment Format v0 (AngaraColumn prep):
- train:
docs/planning/releases/v5/minor/RM-5.16.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: columnar segment on-disk format v0 + column cache + zone maps; baseline read-only scan surface; see evidence pack for closure notes.
- train:
- RM-5.15.13 (closed) — Page-Based Default + Overlay Hydrate Bridge:
- train:
docs/planning/releases/v5/minor/RM-5.15.13.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: page-based storage default ON, hydrate bridge restores persistent tables on startup,
configurable
flush_on_commitfor snapshotted tables.
- train:
- RM-5.15.12 (closed) — Txlog Path Guardrails & Regression Tests:
- train:
docs/planning/releases/v5/minor/RM-5.15.12.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: regression tests for commit conflict 40001 (hotfix follow-up), runtime warning for split-directory misconfiguration, and risk closure.
- train:
- RM-5.13.1 (in_review) — AQP hardening fix release:
- train:
docs/planning/releases/v5/minor/RM-5.13.1.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: bounded async feedback ingest path, self-join-safe operator identity matching, and documented
AQP capacity knob (
ANGARABASE_AQP_STORE_CAPACITY_MB) for deterministic bounded advisory store behavior.
- train:
- RM-5.15.11 (closed) — IR Executor Refactor + Unwrap/Expect Cleanup:
- train:
docs/planning/releases/v5/minor/RM-5.15.11.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - note: no user-facing SQL/ops contract changes (refactor-only train; internal executor module decomposition
- guardrails).
- train:
- RM-5.12.3 (closed) — Comparative Benchmark Infrastructure:
- train:
docs/planning/releases/v5/minor/RM-5.12.3.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: SQL-level benchmark suite (B1-B7), AngaraBase-vs-PostgreSQL comparator reports, SQL coverage corpus and score reporting, and optional nightly SQL benchmark hook.
- train:
- RM-5.12.2 (closed) — Parallel Performance Polish:
- train:
docs/planning/releases/v5/minor/RM-5.12.2.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: removed sequential join-build merge bottleneck via shared partition build path; preserved join
accounting telemetry continuity in
EXPLAIN ANALYZE.
- train:
- RM-5.12.1 (closed) — AngaraParallel gap closure:
- train:
docs/planning/releases/v5/minor/RM-5.12.1.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: partitioned parallel join build phase, settings-governed DOP caps
(
ANGARABASE_PARALLEL_DOP_CAP_GLOBAL/ANGARABASE_PARALLEL_DOP_CAP_QUERY), andEXPLAIN ANALYZEparallel join counters (join_build_rows,join_probe_rows).
- train:
- RM-5.10.1 (closed) — AngaraVector gap closure:
- train:
docs/planning/releases/v5/minor/RM-5.10.1.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: execution mode contract aligned to
auto/force_vector/force_row, explicit vector bridges (RowToColumnBridge,BatchToRowBridge), and column-native vector hash kernels used in vector join/aggregate path.
- train:
- RM-5.10 (closed) — AngaraVector phase-1:
- train:
docs/planning/releases/v5/minor/RM-5.10.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: vector execution mode now covers join/aggregate plan paths and
EXPLAINmarks vector operators (VectorHashJoin,VectorAgg) when vector mode is active.
- train:
- RM-5.9 (closed) — AngaraVector phase-0:
- train:
docs/planning/releases/v5/minor/RM-5.9.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights: introduced vector batch format baseline (
batch_sizedefault 1024), scan/filter/project vector path, and bounded per-query vector memory budget knobs.
- train:
- RM-5.8.1 (closed) — AngaraMemory async snapshots + per-table scheduler:
- train:
docs/planning/releases/v5/minor/RM-5.8.1.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights:
durability='snapshotted'no longer performs immediate hot-path page persistence; checkpoint worker now honors per-tablecheckpoint_interval_msscheduling.
- train:
- RM-5.8 (closed) — AngaraMemory phase-1:
- train:
docs/planning/releases/v5/minor/RM-5.8.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights:
durability='logged'|'snapshotted', opt-ineviction_policy='fifo', and SQL-visible memory-table runtime counters insys.tables.
- train:
- RM-5.7 (closed) — AngaraMemory phase-0:
- train:
docs/planning/releases/v5/minor/RM-5.7.md - release notes:
docs/planning/releases/v5/RELEASE_NOTES.md - highlights:
storage='memory'table surface, fail-closedmax_rowsenforcement (54023), and volatiledurability='none'restart semantics.
- train:
- RM-5.6.5 (closed) — reliability engineering closure:
- train:
docs/planning/releases/v5/minor/RM-5.6.5/RM-5.6.5.md - release notes:
docs/planning/releases/v5/minor/RM-5.6.5/release_notes.md - note: no user-facing SQL/ops contract changes (runtime panic-hardening + CI governance).
- train:
- RM-5.6.4 (closed) — architecture governance closure:
- train:
docs/planning/releases/v5/minor/RM-5.6.4/RM-5.6.4.md - release notes:
docs/planning/releases/v5/minor/RM-5.6.4/release_notes.md - note: no user-facing SQL/ops contract changes (layering/dependency CI guardrails).
- train:
- RM-5.6.3 (closed) — native packaging + secure init-first bootstrap:
- train:
docs/planning/releases/v5/minor/RM-5.6.3/RM-5.6.3.md - release notes:
docs/planning/releases/v5/minor/RM-5.6.3/release_notes.md - highlights:
- secure init CLI hardening (
--superuser-password-file|--superuser-password-env,--require-auth, explicit--insecure-trust) - native RPM/DEB packaging manifests with init-first service start fence (
ConditionPathExists=/var/lib/angarabase/data/VERSION) - release signing helpers and deterministic repo-layout scaffolding for package publication
- secure init CLI hardening (
- train:
- RM-5.6.2 (closed) — packaging baseline for operator install path:
- train:
docs/planning/releases/v5/minor/RM-5.6.2/RM-5.6.2.md - release notes:
docs/planning/releases/v5/minor/RM-5.6.2/release_notes.md - highlights:
- portable
x86_64-unknown-linux-gnuarchive build in pinned RHEL8/UBI8 (glibc 2.28) environment - Gentoo source ebuild baseline with systemd/OpenRC assets
- runtime fail-closed glibc compatibility guard (
glibc >= 2.28) with operator-facing support contact message
- portable
- train:
- RM-5.6.1 (closed) — architecture hygiene patch:
- train:
docs/planning/releases/v5/minor/RM-5.6.1/RM-5.6.1.md - release notes:
docs/planning/releases/v5/minor/RM-5.6.1/release_notes.md - note: no user-facing SQL/ops contract changes (AngaraBook: no user-facing changes)
- train:
- RM-5.5 / RM-5.6 (closed) — advanced diagnostics + pilot validation:
- trains:
docs/planning/releases/v5/minor/RM-5.5/RM-5.5.mddocs/planning/releases/v5/minor/RM-5.6/RM-5.6.md
- highlights:
- wait-event taxonomy and usage stats surfaces (
sys.table_stats,sys.index_stats) with bounded reset semantics - OTel-style span export knobs for query-stage triage evidence (
ANGARABASE_OTEL_*) - production pilot evidence updated with workload command and reprioritization notes
- wait-event taxonomy and usage stats surfaces (
- trains:
- AngaraBook security docs expanded:
- pages:
security/overview.md,security/authorization.md,security/authentication.md,security/audit.md,security/encryption.md,security/break-glass.md,security/hardening.md - highlights: end-to-end user-facing security documentation for RM-4.25/RM-5.3/RM-5.3.1/RM-5.4 surfaces (RBAC/RLS/break-glass/audit/TDE/client-encrypted columns)
- pages:
- RM-5.4 (closed) — Security Layer Reinforcement Phase 2:
- train:
docs/planning/releases/v5/minor/RM-5.4/RM-5.4.md - release notes:
docs/planning/releases/v5/minor/RM-5.4/release_notes.md - highlights: Audit v1 DML policy controls (
off|allowlist|denylist), RLS v1 masking/provenance introspection, and client-encrypted columns v0 metadata contract with fail-closed predicate bounds
- train:
- RM-5.3.1 (closed) — TDE patch for audit-at-rest:
- train:
docs/planning/releases/v5/minor/RM-5.3.1/RM-5.3.1.md - release notes:
docs/planning/releases/v5/minor/RM-5.3.1/release_notes.md - highlights: audit sink bytes are encrypted when TDE is enabled,
sys.audit_logstays readable with key material, missing key is fail-closed for audit sink read/write
- train:
- RM-5.3 (closed) — TDE v0 baseline:
- train:
docs/planning/releases/v5/minor/RM-5.3/RM-5.3.md - release notes:
docs/planning/releases/v5/minor/RM-5.3/release_notes.md - highlights: fail-closed TDE enablement for page/WAL at-rest encryption,
sys.settingsmetadata-only introspection for key id/rotation timestamp, restore fail-closed without keys
- train:
- RM-5.2 (closed) — module decomposition phase-1 (
.inc.rselimination, security module layout, pgwire tests split, architecture doc consolidation) completed as refactor-only train:- train:
docs/planning/releases/v5/minor/RM-5.2/RM-5.2.md - release notes:
docs/planning/releases/v5/minor/RM-5.2/release_notes.md - note: no user-facing SQL/ops contract changes
- train:
- See current train planning:
docs/planning/releases/README.md - RM-5.1 (closed) — module decomposition phase-0 (
sys_catalog,virtual_catalog,metrics) completed as refactor-only train:- train:
docs/planning/releases/v5/minor/RM-5.1/RM-5.1.md - release notes:
docs/planning/releases/v5/minor/RM-5.1/release_notes.md - note: no user-facing SQL/ops contract changes
- train:
- RM-4.0 line (closed) — major-line closure completed with truth-of-now planning sync:
- major entry point:
docs/planning/releases/v4/RM-4.0.md - train index:
docs/planning/releases/v4/minor/README.md - rollup changelog:
docs/planning/releases/v4/CHANGELOG.md - closure evidence:
docs/planning/evidence/release_lines/rm-4.0/major_closure_20260216.md - transition:
docs/planning/releases/v5/RM-5.0.md
- major entry point:
- RM-4.25.1 (closed) — Security Hardening & RLS Optimization:
- train:
docs/planning/releases/v4/minor/RM-4.25.1/RM-4.25.1.md - release notes:
docs/planning/releases/v4/minor/RM-4.25.1/release_notes.md - highlights: fail-closed IR RLS predicate checks (
0A000on unsupported complexity), mandatory SecurityContext enforcement (42501in non-trust modes), bounded planner-stage RLS rewrite for IR SELECT, and audit fsync barriers for break-glass lifecycle events
- train:
- RM-4.25 (closed) — Security Reinforcement Phase 1:
- train:
docs/planning/releases/v4/minor/RM-4.25/RM-4.25.md - release notes:
docs/planning/releases/v4/minor/RM-4.25/release_notes.md - highlights: secure
--initsuperuser bootstrap, RLS v0 on reads+writes, break-glass lifecycle, audit chain verification,sys.*security introspection views/functions
- train:
- RM-4.21 (closed) — AngaraStat Level 2 reservoir stats (bounded):
- train:
docs/planning/releases/v4/minor/RM-4.21/RM-4.21.md - release notes:
docs/planning/releases/v4/minor/RM-4.21/release_notes.md - highlights:
stats_reservoir_size, Level 2 histogram/MCV surfaces insys.column_stats
- train:
- RM-4.22 (closed) — query diagnostics v0:
- train:
docs/planning/releases/v4/minor/RM-4.22/RM-4.22.md - release notes:
docs/planning/releases/v4/minor/RM-4.22/release_notes.md - highlights:
EXPLAIN/EXPLAIN ANALYZE, slow query log,angara_stat_activity,angara_stat_statements,angara_top_queries()
- train:
- RM-4.24 (closed) — reliability/efficiency hardening:
- train:
docs/planning/releases/v4/minor/RM-4.24/RM-4.24.md - release notes:
docs/planning/releases/v4/minor/RM-4.24/release_notes.md - highlights:
REINDEX INDEX, BRIN range-efficiency metric, strict storage startup default, no-auth startup guardrail
- train:
- RM-4.24.1 (closed) — mutation policy
no_delete:- train:
docs/planning/releases/v4/minor/RM-4.24.1/RM-4.24.1.md - release notes:
docs/planning/releases/v4/minor/RM-4.24.1/release_notes.md - highlights: unified
mutation_policy,42809guards for DELETE/TRUNCATE and PK/FK updates,sys.tables.mutation_policy
- train:
- RM-4.24.2 (closed) — SQL semantics/stats hardening:
- train:
docs/planning/releases/v4/minor/RM-4.24.2/RM-4.24.2.md - release notes:
docs/planning/releases/v4/minor/RM-4.24.2/release_notes.md - highlights: typed min/max streaming stats, mutation epoch metric, EXPLAIN ANALYZE dry-run for DML, wait-event classification
- train:
- RM-4.24.3 (closed) — SQL/stats closure:
- train:
docs/planning/releases/v4/minor/RM-4.24.3/RM-4.24.3.md - release notes:
docs/planning/releases/v4/minor/RM-4.24.3/release_notes.md - highlights: typed
col_min/col_maxsurfaces, typed reservoir samples with membership-aware UPDATE/DELETE handling,wait_event_typeinangara_stat_activity
- train:
- RM-4.24.4 (closed) — core decomposition for executor:
- train:
docs/planning/releases/v4/minor/RM-4.24.4/RM-4.24.4.md - release notes:
docs/planning/releases/v4/minor/RM-4.24.4/release_notes.md - highlights: internal refactor (
ir_executorsplit into scan/join/aggregate/sort modules), no user-facing SQL/ops contract changes
- train:
- RM-4.15 (closed) — BRIN baseline (bounded):
- train:
docs/planning/releases/v4/minor/RM-4.15/RM-4.15.md - release notes:
docs/planning/releases/v4/minor/RM-4.15/release_notes.md - evidence:
docs/planning/evidence/release_trains/rm-4.15-4.16/release_closure_20260216.md
- train:
- RM-4.16 (closed) — page checksums v0 + verify-pages triage surface:
- train:
docs/planning/releases/v4/minor/RM-4.16/RM-4.16.md - release notes:
docs/planning/releases/v4/minor/RM-4.16/release_notes.md - evidence:
docs/planning/evidence/release_trains/rm-4.15-4.16/release_closure_20260216.md
- train:
- RM-4.17 (closed) — SQL semantics tranche (bounded
WITH,ORDER BY <expr>, deterministic0A000hygiene):- train:
docs/planning/releases/v4/minor/RM-4.17/RM-4.17.md - release notes:
docs/planning/releases/v4/minor/RM-4.17/release_notes.md - evidence:
docs/planning/evidence/release_trains/rm-4.17-4.18/release_closure_20260216.md
- train:
- RM-4.18 (closed) — table partitioning v0 (
RANGE/LIST, routing, pruning, per-partition cascade):- train:
docs/planning/releases/v4/minor/RM-4.18/RM-4.18.md - release notes:
docs/planning/releases/v4/minor/RM-4.18/release_notes.md - evidence:
docs/planning/evidence/release_trains/rm-4.17-4.18/release_closure_20260216.md
- train:
- RM-4.19 (closed) — append-only table mode v0 (
append_onlyDDL/property,42809mutation guards, partition inheritance, rowid watermark):- train:
docs/planning/releases/v4/minor/RM-4.19/RM-4.19.md - release notes:
docs/planning/releases/v4/minor/RM-4.19/release_notes.md - evidence:
docs/planning/evidence/release_trains/rm-4.19-4.20/release_closure_20260216.md
- train:
- RM-4.20 (closed) — AngaraStat Level 1 (
ndv_approx/min/max/null_count,stats_level_maxcontrols, stats observability):- train:
docs/planning/releases/v4/minor/RM-4.20/RM-4.20.md - release notes:
docs/planning/releases/v4/minor/RM-4.20/release_notes.md - evidence:
docs/planning/evidence/release_trains/rm-4.19-4.20/release_closure_20260216.md
- train:
- RM-4.23 (closed) — unified
.adbstorage path for heap tables:- train + gates + evidence:
docs/planning/releases/v4/minor/RM-4.23/RM-4.23.md - runtime routing fixed: user DB writes go to
<db>.adband<db>.atl(notbase.*) - backup/restore note updated:
operations/backup-and-restore.md
- train + gates + evidence:
Milestones (testing-ready)
-
RM-2.3 (closed) — backup/restore baseline is testable:
- cold/offline backup/restore + restore oracle:
docs/planning/releases/v2/minor/RM-2.3/RM-2.3.md - runbook:
angarabook/src/operations/backup-restore.md
- cold/offline backup/restore + restore oracle:
-
RM-2.4 (closed) — execution/compat deepening is pinned:
- train + gates + evidence pointers:
docs/planning/releases/v2/minor/RM-2.4/RM-2.4.md - known issues remain explicit:
angarabook/src/operations/known-issues.md
- train + gates + evidence pointers:
-
RM-2.7 (closed) — backup/restore v2 phase 1a is testable (offline/local baseline):
- train + gates + evidence:
docs/planning/releases/v2/minor/RM-2.7/RM-2.7.md - pinned evidence runner:
tools/backup_restore/evidence_v2_phase1a.sh - AngaraBook page:
operations/backup-and-restore.md
- train + gates + evidence:
-
RM-2.8 (closed) — validation hardening is testable:
- train + gates:
docs/planning/releases/v2/minor/RM-2.8/RM-2.8.md - compat nightly emits
coverage_report.json(probe-level):tools/compat_suite/run.sh
- train + gates:
-
RM-2.9 (closed) — backup/restore v2 phase 1b (online/PITR) is testable:
- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.9/RM-2.9.md - pinned evidence runner:
tools/backup_restore/evidence_v2_phase1b.sh - AngaraBook page:
operations/backup-and-restore.md
- train + gates + pinned pointers:
-
RM-2.10 (closed) — SysCatalog identity + native
sys.*introspection is available:- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.10/RM-2.10.md - identity file:
storage.data_directory/identity_v0.txt
- train + gates + pinned pointers:
-
RM-2.11 (closed) —
pg_catalogsemantics are rooted in SysCatalog (trace-driven) + identity rehearsal gate:- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.11/RM-2.11.md - identity rehearsal runner:
tools/release_preflight/rehearsal_identity.sh(renamed fromrehearsal_identity_rm211.sh) - compat matrix (truth source):
angarabook/src/operations/client-compatibility.md
- train + gates + pinned pointers:
-
RM-2.12 (closed) — upgrade rehearsal is wired into nightly discipline + docs anti-drift is enforced:
- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.12/RM-2.12.md - rehearsal runner:
tools/upgrade_rehearsal/run.sh - preflight wiring:
tools/release_preflight/run.sh - docs validator:
docs/validate-docs.sh
- train + gates + pinned pointers:
-
RM-2.13 (closed) — code health hardening: prevent god-files growth (touched-file budget gate):
- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.13/RM-2.13.md - gate runner:
tools/lint/code_health.sh - PR wiring:
tools/ci_pr.sh
- train + gates + pinned pointers:
-
RM-2.14 (closed) — admin remote transport v0 (TCP) +
angara-cliremote identity:- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.14/RM-2.14.md - server: env
ANGARABASE_ADMIN_ADDR+crates/angarabased/src/admin_tcp.rs - client:
angara-cli admin identity --addr <host:port> [--json]
- train + gates + pinned pointers:
-
RM-2.15 (closed) — persisted SysCatalog v0: DDL survives restart:
- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.15/RM-2.15.md - persisted catalog file:
storage.data_directory/sys_catalog_v0.txt
- train + gates + pinned pointers:
-
RM-2.16 (closed) — graceful shutdown contract (bounded):
- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.16/RM-2.16.md - env knob:
ANGARABASE_SHUTDOWN_TIMEOUT_MS
- train + gates + pinned pointers:
-
RM-2.17 (closed) — admin/ops via pgwire (SQL/sys.*, no Unix sockets):
- train + gates + pinned pointers:
docs/planning/releases/v2/minor/RM-2.17/RM-2.17.md - sys views:
sys.identity,sys.health,sys.settings - optional SQL shutdown (fail-closed):
ANGARABASE_ALLOW_SQL_SHUTDOWN=1+SELECT sys.request_shutdown()
- train + gates + pinned pointers:
Released tags
Список released tags и ссылки на release notes см. в CHANGELOG.md → “Released”.