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 на уровне, достаточном для принятия решений: выбор конфигурации, диагностика проблем, оценка применимости.
Подробный разбор подсистем — в разделах Концепции и SQL Reference.
Многоуровневая архитектура
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-кодом, а не неожиданный результат. Это предсказуемо и безопасно для продакшена.
Дополнительные материалы
- Хранение данных:
concepts/storage-engine.md— row-store, страницы, pluggable storage. - Обработка запросов:
concepts/query-processing.md— парсер, планировщик, оптимизатор, исполнитель. - Каталог и метаданные:
concepts/catalog-and-metadata.md— SysCatalog и системные представления.
Quickstart: запуск за 5 минут
Поднимаем angarabase-server, подключаемся через psql, выполняем базовый
DDL/DML и проверяем, что данные и каталог переживают рестарт.
Требования
- Linux x86_64, glibc ≥ 2.28. Portable-сборка проверяет это сама: при более
старом glibc
angarabase-serverвыходит fail-closed с явным сообщением о несовместимости. - Один из вариантов установки: portable-архив
x86_64-unknown-linux-gnuили сборка из исходников (Rust toolchain — см.rust-toolchain.toml). - Клиент
psql(или любой PostgreSQL-совместимый).
Установка
Portable-архив
VER=0.6.8
mkdir -p /opt/angarabase
tar -xzf angarabase-$VER-x86_64-unknown-linux-gnu.tar.gz -C /opt/angarabase
/opt/angarabase/angarabase-$VER/bin/angarabase-server --version
Сборка из исходников
cargo build --release -p angarabase-server -p angara-cli
# бинарь: target/release/angarabase-server
Шаг 1. Конфиг
AngaraBase не стартует с «магических» дефолтов — путь к данным и адрес задаются
явно. Минимальный angarabase.conf:
[server]
addr = "127.0.0.1:5432"
[storage]
data_directory = "/var/lib/angarabase/data"
transaction_log_directory = "/var/lib/angarabase/txlog"
[logging]
log_level = "info"
Путь к конфигу передаётся флагом --config-path; без флага сервер ищет
/etc/angarabase/angarabase.conf. Если конфиг найден, но содержит устаревшие
ключи, сервер падает fail-closed (exit 78) с их перечислением — молчаливого
отката к дефолтам нет.
Шаг 2. Инициализация инстанса
Однократная инициализация создаёт каталог, data/ и txlog/ по путям из
конфига. --init — отдельный однопроходный режим: бинарь инициализирует
инстанс и завершает работу с кодом 0.
angarabase-server --config-path ./angarabase.conf --init \
--superuser angara_root \
--superuser-password-file ./superuser.pw \
--auth-mode scram --require-auth
--auth-mode scram— SCRAM-SHA-256 (режим по умолчанию;scram— алиас полного имениscram-sha-256).--require-auth— fail-closed: init откажется, если для не-trustрежима не задан пароль суперпользователя.- Пароль:
--superuser-password-file <файл>(рекомендуется) или--superuser-password-env <VAR>. Инлайн-форма--superuser-password '...'тоже есть, но пароль попадёт в историю шелла.
Init печатает instance_id, data_directory, txlog_directory. Повторный
init на уже инициализированном каталоге — fail-closed (already initialized).
⚠️ Insecure-режимы — только явно.
trust/no-auth(без аутентификации) разрешён лишь с явным--insecure-trust:--auth-mode trust --insecure-trust. Без этого флага init откажется. Используйте только в изолированных лабах, не в сети.
Альтернатива без редактирования конфига — переопределить корень инстанса
флагами; тогда data/ и txlog/ создаются под указанным каталогом:
angarabase-server --config-path ./angarabase.conf --init \
--init-root /var/lib/angarabase \
--superuser angara_root --superuser-password-file ./superuser.pw \
--auth-mode scram --require-auth
Шаг 3. Запуск сервера
angarabase-server --config-path ./angarabase.conf
Сервер слушает 127.0.0.1:5432 (из конфига). Бинд на не-loopback адрес без
TLS/auth тоже fail-closed: нужен явный --allow-insecure (или
[security].allow_insecure = true). Это флаг для контролируемых сред, не для
прода.
⚠️
--allow-insecure/--allow-insecure-no-auth/--devвключают небезопасные пресеты (без TLS, без обязательной аутентификации). Допустимы только в dev/test.
Шаг 4. Подключение через psql
psql "host=127.0.0.1 port=5432 user=angara_root dbname=base password=<пароль> sslmode=disable"
base — логическая база по умолчанию (схема public).
SecurityContext (режимы scram / cert)
В режимах scram/cert защищённый SQL (таблицы под RLS, tenant-scoped данные)
требует контекста сессии — иначе политике безопасности не к чему привязаться.
Установите claim сразу после подключения:
SET SESSION CONTEXT 'app.tenant_id' = 'public';
-- эквивалентная краткая форма:
SET app.tenant_id = 'public';
SET SESSION CONTEXT нельзя выполнять внутри открытой транзакции (вернётся
ошибка). Значение читается через current_setting('app.tenant_id') — именно на
нём строятся RLS-политики (см. Авторизация).
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;
Проверка рестартом (DDL переживает перезапуск)
Метаданные CREATE TABLE (каталог) должны сохраняться между перезапусками.
- Остановите сервер (
Ctrl+C). - Запустите снова:
angarabase-server --config-path ./angarabase.conf. - Убедитесь, что таблица на месте:
SELECT table_name FROM sys.tables WHERE table_name = 't';
Интроспекция через 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';
Опционально: shutdown через SQL (fail-closed)
По умолчанию shutdown через SQL выключен (кноб ops.allow_sql_shutdown).
Включить локально/для тестов:
export ANGARABASE_ALLOW_SQL_SHUTDOWN=1
После этого можно запросить остановку из psql:
SELECT sys.request_shutdown();
Операция проходит проверку RBAC и пишется в audit-log; пользователю без прав — отказ.
Если что-то не так
- «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. Несколько команд в одном запросе
psql -c "..." (и любой клиент) может отправить несколько SQL-команд, разделённых ;, одним
Simple Query. AngaraBase выполняет их по порядку и возвращает результат каждой:
psql 'postgresql://angara@127.0.0.1:5432/angara_demo' \
-c "CREATE TABLE t(id int); INSERT INTO t VALUES (1); SELECT count(*) FROM t"
# CREATE TABLE
# INSERT 0 1
# count
# -------
# 1
- Ошибка в любой команде прерывает выполнение остатка строки (как в PostgreSQL).
- Отличие от PostgreSQL — атомарность. PostgreSQL неявно оборачивает всю multi-statement
строку (без явного
BEGIN) в одну транзакцию: при ошибке откатываются и ранее выполненные команды. AngaraBase же фиксирует каждую команду по отдельности (autocommit), поэтому при ошибке в середине строки ранее выполненные команды остаются зафиксированными. Для атомарной миграции оборачивайте набор явно:BEGIN; …; COMMIT(тогда ошибка откатит всё). - Ограничения разбиения. Строка делится по
;, при этом;внутри одинарных кавычек (SELECT 'a;b') не разбивает запрос. Но;внутри строчного (--) или блочного (/* */) комментария, внутри идентификатора в двойных кавычках ("a;b") или внутри dollar-quoted-тела ($$ … ; … $$, например PL/pgSQL-функции и выводpg_dump) разобьёт строку некорректно. Такие команды отправляйте отдельными запросами или черезpsql -f.
1.5. Если что-то пошло не так
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. Автоматические проверки сборки документации помечают расхождение как блокирующее.
Как мы соблюдаем контракты
Контракт без механизма соблюдения — декларация. В AngaraBase используется несколько слоёв принуждения, которые работают вместе.
Type system как первый рубеж
Result<T, Error>вместо panic.unwrap()/expect()в production-коде запрещены.- Bounded generics и trait-объекты вместо dynamic dispatch там, где инвариант можно зафиксировать на уровне типов.
- No-panic policy: сервер не падает из-за пользовательского ввода — он возвращает SQLSTATE.
Restrictive by default + fail-closed
Каждый компонент с ресурсной границей обязан определить:
- свою границу (например,
max_connections,txn.max_write_set_bytes,execution.query_memory_limit_mb), - поведение при её нарушении (явная ошибка с известным 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).
Если вы опираетесь на что-то из этого списка в продакшене — это технический долг на стороне клиента, и очередное обновление 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 (строковое хранилище). In-Memory (AngaraMemory) доступен (bounded) через storage='memory'; Column-Store запланирован.
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 в заголовке
страницы. Отдельного файла для индексов нет.
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 (AngaraMemory) — доступен (bounded)
Движок для хранения данных в оперативной памяти (storage='memory'). Поддерживаются три режима durability:
| Режим | Описание |
|---|---|
volatile | Данные только в памяти; теряются при перезапуске. |
logged | Записи дублируются в WAL; восстановление при перезапуске. |
snapshotted | Периодический snapshot на диск + WAL. |
Статус: доступен (bounded).
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 и не требует блокировок. Читатель никогда не ждёт писателя и наоборот.
Операции записи (оптимистичный конкурентный доступ)
Писатели не удерживают классических блокировок строк. Конкуренция — оптимистичная:
во время транзакции изменения копятся в overlay, а на COMMIT движок проверяет
по версиям, что затронутые данные не изменились с момента snapshot транзакции.
- Если параллельная транзакция успела закоммитить конфликтующее изменение,
«проигравшая» откатывается с
40001(serialization failure) — данные не теряются молча. Счётчик:angarabase_txn_commit_conflicts_total. - Гранулярность конфликта — построчная по умолчанию: параллельные писатели в разные строки одной таблицы оба коммитятся успешно.
- Предикатные
UPDATE/DELETE, которые не могут перечислить конкретные целевые строки (скан по условию), консервативно эскалируют до табличного конфликта: любое параллельное изменение этой таблицы откатит одну из транзакций. Это и есть serialized-fallback — более грубая, но безопасная проверка.
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. Если
нужна строгая сериализуемость, самый прямой путь — уровень
SERIALIZABLE(SSI предотвращает write skew и phantom-ы, конфликтные транзакции прерываются с40001). Как альтернатива — явные блокировкиSELECT ... FOR UPDATE(работают для простых однотабличных запросов сidв проекции; для JOIN/подзапросов возвращается0A000)
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)
Какие типы индексов есть в AngaraBase, когда их использовать и как они взаимодействуют с MVCC.
AngaraTree — index engine
AngaraTree — индексный движок AngaraBase. Индексы хранятся внутри .adb-файла базы данных (страницы с page_type = 1), вместе с 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).
Ресурсные ограничения
Обслуживание индекса ограничено по времени (fail-closed): если вставка/удаление
в индекс не укладывается в бюджет, DML откатывается, а счётчик
angarabase_index_reject_total инкрементируется.
| Ограничение | Конфиг | По умолчанию | При нарушении |
|---|---|---|---|
| Время обслуживания индекса | storage.index_maintenance_budget_ms (env ANGARABASE_INDEX_MAINTENANCE_BUDGET_MS) | 5000 мс (0 — отключить) | MaintenanceBudgetExceeded → DML abort |
Реджект angarabase_index_reject_total покрывает также внутренние пределы
(KeyTooLarge, PageLimitExceeded); отдельного публичного кноба на число
страниц нет.
Наблюдаемость
| Метрика | Описание |
|---|---|
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 для проверки, использует ли оптимизатор индекс. Подробнее — Обработка
запросов.
Перестроение индекса
Полное перестроение индекса выполняется командой REINDEX:
REINDEX INDEX idx_name;
REINDEX CONCURRENTLY INDEX idx_name; -- без долгой блокировки DML
Полезно после частичного восстановления при старте (метрика
angarabase_index_restore_capped_total ≠ 0 означает, что индекс поднят не
полностью) или для возврата места после массовых удалений (merge страниц в v0
нет — место освобождает REINDEX).
Связанные разделы
Концепции (что почитать дальше)
- Обработка запросов — как оптимизатор выбирает и комбинирует индексы.
- Хранение данных — как страницы 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 # включить текст запроса в лог
Подробнее — Диагностика.
Vectorized и параллельное исполнение
| Компонент | Описание | Статус |
|---|---|---|
| AngaraVector | Vectorized/SIMD execution — обработка batch по колонкам вместо row-at-a-time (execution.vector_batch_size) | Доступно (bounded) |
| AngaraParallel | Morsel-driven parallelism — параллельное выполнение на нескольких ядрах (sql.parallel.dop_cap_*) | Доступно (bounded) |
| AngaraAdapt | Adaptive processing — переключение стратегий во время выполнения | В roadmap |
Связанные разделы
Концепции (что почитать дальше)
- Индексы — как оптимизатор выбирает индекс для
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.*) — первые шаги с системными представлениями
- Безопасность — функции интроспекции безопасности
- Диагностика — мониторинг и устранение проблем
- Обработка запросов — как оптимизатор использует метаданные каталога
Жизненный цикл инстанса
Как AngaraBase понимает «кто владеет этими файлами данных»: идентичность инстанса, аренда (Instance Lease) и порядок запуска. Аренда — это то, что даёт безопасное восстановление после аварии и переносимость хранилища между хостами без дампа/восстановления.
Идентичность инстанса
При инициализации инстанс получает устойчивую идентичность:
cluster_id— UUID логического кластера БД.instance_id— UUID конкретного инстанса.- Каталог данных и каталог журнала транзакций — физическое расположение файлов.
Идентичность хранится в двух местах, чтобы пережить как сбой файла, так и сбой каталога:
- VERSION-маркер — бинарный файл с версией формата и идентификаторами.
- Страницы системного каталога — в зарезервированных страницах
base.adbс полными метаданными.
Аренда инстанса (Instance Lease)
Аренда не даёт двум инстансам одновременно писать в одни и те же файлы — а это
прямой путь к повреждению данных. Запись аренды лежит в SysCatalogMetaV0
внутри страниц base.adb и обновляется атомарно полным образом страницы.
Поэтому механизм работает на NFS/SAN, где flock() ненадёжен.
Что записано в аренде
| Поле | Назначение |
|---|---|
holder_id | UUID инстанса-владельца |
acquired_at_unix_s | когда аренда взята (Unix-время, с) |
expires_at_unix_s | когда истекает (TTL) |
holder_pid | PID процесса (диагностика) |
holder_hostname | имя хоста (диагностика) |
Состояния аренды
[Нет] ──acquire──▶ [Held] ──heartbeat──▶ [Held]
▲ │
└──release/expired───┘
│ heartbeat прекратился (краш, разрыв сети)
▼
[Expired] ──takeover──▶ [Held новым инстансом]
- Нет → Held — первый запуск или запуск после штатной остановки.
- Held → Held — периодический heartbeat (по умолчанию каждые 10 с) сдвигает
expires_at. - Held → Нет — штатная остановка немедленно освобождает аренду.
- Held → Expired — heartbeat прекратился (краш, сетевой разрыв); аренда «протухает» по истечении TTL.
- Expired → Held — новый инстанс перехватывает аренду после истечения TTL.
Порядок запуска
- Pre-flight — каталог данных существует и инициализирован, VERSION-маркер совместим, размер страницы совпадает со сборкой бинаря.
- Захват аренды — загрузка системного каталога из
base.adb, затем:- аренды нет → захватить сразу;
- аренда истекла → перехватить (с предупреждением в лог);
- аренда активна → fail-closed с информативной ошибкой (см. ниже);
- принудительный перехват → переопределить активную аренду (опасно).
- Восстановление — проигрывание WAL (backend
file_bin), восстановление in-memory состояния MVCC, запуск heartbeat. - Готов к подключениям — поднимаются слушатели (pgwire, admin), сервер принимает клиентов и продолжает heartbeat до остановки.
Режимы восстановления
recovery_mode виден в sys.identity и принимает три значения:
recovery_mode | Когда |
|---|---|
normal | чистый старт на корректно остановленных данных; WAL не проигрывается |
crash_recovery | предыдущий инстанс завершился аварийно; WAL восстанавливает закоммиченные транзакции, состояние MVCC перестраивается из журнала |
forced_takeover | оператор взял аренду через ANGARABASE_FORCE_LEASE_TAKEOVER=1 — обычно аварийный сценарий |
Разделяемое хранилище (NFS/SAN)
Аренда позволяет нескольким хостам видеть одни и те же файлы, но писать — только одному:
Host A ──┐
├── NFS/SAN ──▶ [data/] [txlog/] [base.adb с арендой]
Host B ──┘
- Failover — Host B перехватывает аренду, если Host A упал.
- Обслуживание/миграция — перенос инстанса между хостами без дампа.
- Тестирование — безопасный прогон на копии боевых данных.
Ограничения: единственный писатель в каждый момент; сетевые разрывы могут вызвать ложное истечение аренды; латентность сетевого хранилища влияет на пропускную способность.
Управление арендой (env-переменные)
Аренда настраивается только переменными окружения — отдельных config-ключей для неё нет.
| Переменная | Назначение | По умолчанию |
|---|---|---|
ANGARABASE_LEASE_TTL_S | срок жизни аренды, с | 30 |
ANGARABASE_LEASE_HEARTBEAT_S | период обновления, с | 10 |
ANGARABASE_FORCE_LEASE_TAKEOVER | аварийный перехват активной аренды | false |
Рекомендации: в сети с нестабильной задержкой увеличьте TTL и heartbeat
(например, 60/20); для быстрой итерации в dev — уменьшите (15/5).
Heartbeat должен оставаться заметно меньше TTL.
⚠️
ANGARABASE_FORCE_LEASE_TAKEOVER=1опасен. Он переопределяет активную аренду, игнорируя живого владельца. Если прежний инстанс на самом деле жив, вы получите двух писателей в одни файлы и повреждение данных. Включайте только когда владелец подтверждённо мёртв (процесс не запущен, хост недоступен). В норме просто дождитесь истечения TTL — перехват произойдёт сам.
Наблюдаемость и диагностика
-- Текущий владелец аренды и режим восстановления
SELECT lease_holder_id, lease_holder_hostname, lease_expires_at, recovery_mode
FROM sys.identity;
-- Здоровье инстанса
SELECT uptime_seconds, txn_commit_epoch_current
FROM sys.health;
События аренды пишутся в лог сервера: захват, перехват, отказ heartbeat, освобождение.
Типичные проблемы
| Симптом | Диагноз | Что делать |
|---|---|---|
Cannot start: database files are owned by another instance | активная аренда не даёт стартовать | дождаться истечения TTL или убедиться, что прежний инстанс мёртв |
| Частые перехваты аренды | нестабильная сеть или конкуренция за ресурсы | увеличить TTL, проверить сеть/диск |
MVCC recovery failed | повреждённый журнал транзакций | проверить ФС, при необходимости восстановиться из бэкапа |
Безопасность: аренда не аутентифицирует — права доступа ФС и сетевые ограничения по-прежнему обязательны, особенно на разделяемом хранилище.
Связанные разделы
Концепции
- Хранение данных — datadir, который защищает аренда.
- Транзакции и MVCC — что происходит с активными
транзакциями при
forced_takeover.
How-to
- Crash recovery — операционные процедуры восстановления после аварии.
- Резервное копирование и восстановление — как защитить datadir и снять снапшот.
Справочник
- Системные представления
sys.*—sys.identity,sys.healthдля диагностики аренды. - Известные ограничения и SQLSTATE — раздел
ошибок
INSTANCE_*.
Обзор совместимости SQL
AngaraBase реализует подмножество PostgreSQL SQL через pgwire-протокол.
Принцип — fail-closed: неподдерживаемая конструкция возвращает явный
SQLSTATE (чаще всего 0A000 feature_not_supported), а не молчаливый
некорректный результат. Эта страница — карта того, что поддержано, и как быстро
интерпретировать ошибки.
Стандартные SQL-конструкции
Матрица того, что AngaraBase понимает в запросах. Поддерживается — корректная
семантика с pinned-тестами; Частично — работает с ограничениями (см.
заметку); 0A000 — неподдержанная форма возвращает детерминированную ошибку.
Запросы (SELECT)
| Конструкция | Статус | Заметка |
|---|---|---|
SELECT … FROM … WHERE …, LIMIT, OFFSET | ✅ Поддерживается | предикаты: сравнения, IN, BETWEEN, IS [NOT] NULL, AND/OR/NOT, boolean-колонка как предикат |
ORDER BY <col> / <expr> / порядковый номер | ✅ Поддерживается | NULLS FIRST/LAST и COLLATE → 0A000; неверный ordinal → 42P10 |
DISTINCT | ✅ Поддерживается | DISTINCT ON (...) → 0A000 |
GROUP BY (в т.ч. многоключевой) · HAVING | ✅ Поддерживается | агрегаты COUNT/SUM/MIN/MAX/AVG; HAVING без GROUP BY тоже |
WITH (CTE, non-recursive) | ✅ Поддерживается | CTE как источник в FROM; WITH RECURSIVE и data-modifying CTE → 0A000 (recursive — planned v0.7) |
Подзапросы: IN (…), EXISTS/NOT EXISTS, скалярный в SELECT | ✅ Поддерживается | коррелированные поддержаны |
Множества: UNION, UNION ALL, INTERSECT, EXCEPT | ✅ Поддерживается | hash-based dedup |
JOIN
| Конструкция | Статус | Заметка |
|---|---|---|
INNER, LEFT [OUTER], RIGHT [OUTER], FULL [OUTER], CROSS | ✅ Поддерживается | все пять видов |
| Условие соединения | ✅ ON <expr> | USING (...) и NATURAL JOIN → 0A000 |
LATERAL (…) | ✅ Поддерживается | коррелированная производная таблица |
CROSS JOIN бюджет строк | ⚠️ Частично | лимит sql.join.max_cross_join_rows (деф. 1 000 000); превышение → 54000 |
Оконные функции (OVER (…))
| Функция | Статус | Заметка |
|---|---|---|
ROW_NUMBER, RANK, DENSE_RANK | ✅ Поддерживается | PARTITION BY / ORDER BY |
LAG, LEAD, FIRST_VALUE, LAST_VALUE | ✅ Поддерживается | |
SUM/COUNT/AVG/MIN/MAX OVER (…) | ✅ Поддерживается | оконные агрегаты |
NTILE, именованные окна (WINDOW-clause) | ❌ 0A000 |
DDL / DML / типы
Подробные таблицы и Expected SQLSTATE — на страницах раздела:
| Тема | Страница | Статус |
|---|---|---|
| Типы данных | 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 |
Ключевые DDL-границы: CREATE MATERIALIZED VIEW поддержан, обычный CREATE VIEW
— planned (0A000), CREATE TRIGGER — non-goal (0A000), FOREIGN KEY —
принимается как NOT ENFORCED.
Коды ошибок (SQLSTATE) — быстрый справочник
| SQLSTATE | Имя | Типичный сценарий |
|---|---|---|
0A000 | feature_not_supported | WITH RECURSIVE, JOIN … USING/NATURAL, NTILE, именованные окна, DISTINCT ON, обычный CREATE VIEW (planned), CREATE TRIGGER (non-goal), сложные RLS-предикаты |
54000 | program_limit_exceeded | CROSS JOIN сверх бюджета sql.join.max_cross_join_rows (деф. 1 000 000) |
23514 | check_violation | роутинг секций: нет подходящей партиции и нет DEFAULT |
42809 | wrong_object_type | UPDATE/DELETE на append-only; PK/FK update под no_delete |
22023 | invalid_parameter_value | неверный stats_level_max, break-glass TTL, setval вне [MINVALUE..MAXVALUE] |
42501 | insufficient_privilege | нет ролей для security-операций, нет SecurityContext |
25001 | active_sql_transaction | SET SESSION CONTEXT внутри активной транзакции |
42P10 | invalid_column_reference | ORDER BY по номеру вне диапазона колонок |
2200H | sequence_generator_limit_exceeded | nextval за MAXVALUE/MINVALUE без CYCLE |
55000 | object_not_in_prerequisite_state | currval(seq) до первого nextval в этой сессии |
42P07 | duplicate_object | CREATE SEQUENCE существующего имени без IF NOT EXISTS |
42P01 | undefined_table | DROP SEQUENCE / nextval / currval / setval несуществующей последовательности |
428C9 | generated_always | INSERT явного non-NULL в GENERATED ALWAYS AS IDENTITY |
Полный список с контекстом: Известные ограничения и SQLSTATE.
Подключение ORM и инструментов
ORM и клиенты (DBeaver, psql, Hibernate, Django и др.) при подключении выполняют
служебные pg_catalog-запросы. AngaraBase поддерживает базовую интроспекцию
pg_catalog, нужную для подключения этих инструментов. Если клиент не
подключается, проверьте Совместимость клиентов.
Если запрос зависает (нет ответа), это ошибка с нашей стороны — пожалуйста, соберите артефакты по инструкции в Поддержке и сообщите нам.
Встроенные функции SQL
| Функция | Сигнатура | Описание |
|---|---|---|
NOW() | () → timestamp | Текущее время UTC |
CURRENT_TIMESTAMP | () → timestamp | Алиас для NOW() |
date_trunc(field, ts) | (text, timestamp) → timestamp | Усечение до field (second…millennium); неизвестное поле → NULL |
set_config(name, val, local) | (text, text, bool) → text | Заглушка: возвращает val (совместимость с Django) |
obj_description(oid, cat) | (oid, text) → text | Заглушка: возвращает NULL (интроспекция Django) |
Видимость векторного выполнения
Когда режим выполнения допускает векторный путь
(ANGARABASE_SQL_EXECUTION_MODE=auto для поддержанных планов или force_vector),
EXPLAIN показывает имена векторных операторов: VectorSeqScan, VectorFilter,
VectorProject, VectorHashJoin, VectorAgg. Если форму плана AngaraVector не
поддерживает, в EXPLAIN остаются строчные (row) операторы.
Режимы ANGARABASE_SQL_EXECUTION_MODE:
auto(по умолчанию) — Stable векторный путь только для полностью поддержанных форм, иначе детерминированный откат на строчный;force_row— Stable всегда строчный исполнитель;force_vector— Experimental fail-closed сfeature_not_supported, если векторное выполнение невозможно; для целевого тестирования, не для production-нагрузки в0.6.x.
Опции таблиц AngaraMemory
CREATE TABLE ... WITH (...) поддерживает bounded-таблицы в памяти:
storage='memory'— Baseline движок таблиц AngaraMemory;durability='none'|'logged'|'snapshotted'— Baseline volatile/durable;max_rows=<n>— Stable жёсткий лимит строк; переполнение fail-closed (54023);eviction_policy='error'|'fifo'— Experimental по умолчаниюerror;checkpoint_interval_ms=<n>— Baseline имеет смысл только приdurability='snapshotted'.
Если max_rows не задан, применяется bounded-дефолт из политики инстанса. При
durability='snapshotted' горячий путь DML не персистит страницы немедленно —
запись планирует checkpoint-воркер по checkpoint_interval_ms.
Ссылки
Data types
Справочник типов данных AngaraBase: что реально поддержано, что — нет, и какой
SQLSTATE возвращается при приведении. Источник истины — реестр типов движка
(SQL_TYPE_REGISTRY); уровни поддержки сверены по нему, а не по наличию OID в
виртуальном pg_catalog.
Поддерживаемые типы
Stable — production-ready, есть pinned-тест. Baseline — реализован и пригоден,
но тестовое покрытие уже.
| SQL type | Алиасы | pg_oid | Уровень | Заметки |
|---|---|---|---|---|
BOOLEAN | BOOL | 16 | Stable | TRUE / FALSE / NULL |
SMALLINT | INT2 | 21 | Baseline | 16-бит знаковое |
INTEGER | INT, INT4 | 23 | Stable | 32-бит знаковое |
BIGINT | INT8 | 20 | Stable | 64-бит знаковое |
REAL | FLOAT4 | 700 | Baseline | Одинарная точность |
DOUBLE PRECISION | FLOAT8 | 701 | Stable | Двойная точность |
NUMERIC | DECIMAL | 1700 | Baseline | Точное число (Decimal-backed); строгий парс при явном cast |
TEXT | — | 25 | Stable | Строка переменной длины |
VARCHAR(n) | CHARACTER VARYING | 1043 | Baseline | Строка с лимитом (text-backed) |
CHAR(n) | BPCHAR, CHARACTER | 1042 | Baseline | Строка фиксированной длины (text-backed) |
MVARCHAR(n) | — | 46001 | Baseline | 1С-совместимый национальный VARCHAR: UTF-16LE-семантика, сравнение без учёта регистра и хвостовых пробелов, своя нормализация ключа индекса |
BYTEA | — | 17 | Stable | Двоичная строка переменной длины |
UUID | — | 2950 | Baseline | Только явные приведения; невалидный текст → 22P02 |
DATE | — | 1082 | Baseline | Text-backed; минимальная валидация |
TIMESTAMP | — | 1114 | Baseline | Дата-время без таймзоны (text-backed) |
TIMESTAMPTZ | — | 1184 | Baseline | Парсится для cast / AS OF; смещение не сохраняется |
MVARCHAR — национальный VARCHAR для 1С
MVARCHAR — собственный тип AngaraBase для совместимости с 1С: сравнение
регистронезависимое и без учёта хвостовых ASCII-пробелов, длина задаётся как
MVARCHAR(N), для индекса применяется отдельная нормализация ключа.
CREATE TABLE catalog (code MVARCHAR(16), name MVARCHAR(255));
-- 'Тест ' и 'тест' сравниваются как равные
Text-backed temporal types
DATE / TIMESTAMP / TIMESTAMPTZ хранятся в text-backed режиме:
- Сравнения — текстовые (лексикографические); формат ISO 8601 гарантирует корректный порядок.
TIMESTAMPсериализуется в UTC без смещения (2026-05-07 14:30:00.123); хвостовые нули микросекунд обрезаются.- BRIN-индексы на
date/timestamp/timestamptzподдерживаются (текстовые min/max).
Planned (пока недоступны)
Эти типы зарегистрированы в pg_catalog для интроспекции, но не пригодны к
использованию — приведение к ним возвращает 0A000:
| SQL type | pg_oid | Статус |
|---|---|---|
TIME | 1083 | Planned |
INTERVAL | 1186 | Planned |
JSON | 114 | Planned (функции json_agg / json_build_object возвращают text) |
JSONB | 3802 | Planned |
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;
SELECT '550e8400-e29b-41d4-a716-446655440000'::UUID;
Expected SQLSTATE
| Ситуация | SQLSTATE |
|---|---|
Неподдерживаемый/Planned тип в DDL или cast (TIME, INTERVAL, JSON, JSONB) | 0A000 |
Невалидный текст при приведении (например, в NUMERIC / UUID / float) | 22P02 |
NULLS FIRST / NULLS LAST | 0A000 |
Links
- SQL compatibility overview: overview.md
- DDL (CREATE TABLE с типами): ddl.md
- Known issues: Known issues
DDL — Data Definition Language
Справочник поддерживаемых 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— не обязателен; до одного на таблицу, inline (col TYPE PRIMARY KEY) или table-level (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 MATERIALIZED VIEW / REFRESH MATERIALIZED VIEW | поддержано |
Обычный CREATE VIEW (невещественный) | Planned → 0A000 |
CREATE TRIGGER | non-goal → 0A000 |
Материализованное представление сохраняет результат запроса на диск:
CREATE MATERIALIZED VIEW public.mv_sum AS
SELECT SUM(val) AS s FROM public.src;
-- пересчёт по требованию:
REFRESH MATERIALIZED VIEW public.mv_sum;
-- запланированный пересчёт:
CREATE MATERIALIZED VIEW public.mv_events
WITH (refresh_mode = 'scheduled', refresh_interval = '1s') AS
SELECT SUM(v) AS s FROM public.events;
REFRESH MATERIALIZED VIEW нельзя выполнять внутри транзакции.
CREATE / ALTER / DROP SEQUENCE
AngaraBase поддерживает first-class объекты-последовательности
(SEQUENCE) — 0.6.3.7. Они сохраняются в 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 |
Обычный CREATE VIEW (Planned) | 0A000 |
CREATE TRIGGER (non-goal) | 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
Справочник поддерживаемых 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
0.6.3.7 (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)
0.6.3.7 (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;
Начиная с 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
0.6.3.7 (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
0.6.3.7: 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
Справочник поддерживаемых форм запросов: CTE, JOIN, подзапросы, множества (UNION/INTERSECT/EXCEPT), оконные функции, агрегация, сортировка, статистические поверхности.
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
Поддерживаются все пять видов: INNER, LEFT [OUTER], RIGHT [OUTER],
FULL [OUTER], CROSS.
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;
SELECT a.id, b.name
FROM orders a
FULL OUTER JOIN customers b ON a.customer_id = b.id;
Условие соединения задаётся только через ON <expr> (для CROSS JOIN условие не
нужно). USING (...) и NATURAL JOIN не поддерживаются — 0A000.
CROSS JOIN ограничен бюджетом числа строк sql.join.max_cross_join_rows
(по умолчанию 1 000 000; env ANGARABASE_MAX_CROSS_JOIN_ROWS); превышение —
54000 program_limit_exceeded.
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;
DISTINCT поддерживается; DISTINCT ON (...) — 0A000.
Подзапросы
Поддерживаются IN (...), EXISTS / NOT EXISTS и скалярные подзапросы в
SELECT-списке (в т.ч. коррелированные):
SELECT * FROM orders o WHERE EXISTS (SELECT 1 FROM items i WHERE i.order_id = o.id);
SELECT id, (SELECT COUNT(*) FROM items i WHERE i.order_id = o.id) AS n FROM orders o;
SELECT * FROM t WHERE id IN (SELECT order_id FROM items);
Множества (UNION / INTERSECT / EXCEPT)
SELECT id FROM a
UNION -- с дедупликацией
SELECT id FROM b;
SELECT id FROM a UNION ALL SELECT id FROM b; -- без дедупликации
SELECT id FROM a INTERSECT SELECT id FROM b;
SELECT id FROM a EXCEPT SELECT id FROM b;
Оконные функции (OVER (...))
Поддерживаются ROW_NUMBER, RANK, DENSE_RANK, LAG, LEAD, FIRST_VALUE,
LAST_VALUE и оконные агрегаты SUM/COUNT/AVG/MIN/MAX с PARTITION BY /
ORDER BY:
SELECT id, grp,
ROW_NUMBER() OVER (PARTITION BY grp ORDER BY id) AS rn,
SUM(amount) OVER (PARTITION BY grp) AS grp_total
FROM t;
Не поддерживаются (0A000): NTILE, именованные окна (WINDOW-clause).
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 |
|---|---|
WITH RECURSIVE | 0A000 |
Data-modifying CTEs (WITH … INSERT/UPDATE/DELETE) | 0A000 |
DISTINCT ON (...) | 0A000 |
NTILE, именованные окна (WINDOW-clause) | 0A000 |
JOIN … USING (...) / NATURAL JOIN | 0A000 |
ORDER BY ... NULLS FIRST|LAST, COLLATE | 0A000 |
AngaraStat surfaces
Встроенные статистические представления — то, на что опирается планировщик при
оценке кардинальности. Полезны, чтобы понять, по каким колонкам собрана
статистика (histogram/MCV/HLL) и насколько она свежа (*_epoch); пустые
histogram/MCV означают, что для колонки ещё не набран Level 2.
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 / data-modifying CTE | 0A000 |
DISTINCT ON, NTILE, именованные окна | 0A000 |
ORDER BY ... NULLS FIRST|LAST / COLLATE | 0A000 |
JOIN ... USING (...) / NATURAL JOIN | 0A000 |
CROSS JOIN сверх бюджета строк | 54000 |
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
Справочник секционирования таблиц: 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;
Расширение AngaraBase. В стандартном PostgreSQL отдельного
DROP PARTITIONнет — там это два шага:ALTER TABLE ... DETACH PARTITION+DROP TABLE. ЗдесьDROP PARTITION <name>удаляет дочернюю партицию одной командой.
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 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 |
mtls | mTLS environments | Client TLS certificate validated against CA (also mtls+scram) |
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',
'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 thatauth.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 chain is append-only — tampering is detected (not silently repaired); recovery is an operator action.- 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. |
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
ANGARABASE_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 exceedsANGARABASE_SECURITY_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',
'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: TLS-совместимость и тестирование
Что доступно сейчас: транспортное шифрование (TLS) на ГОСТ-наборах. TDE на ГОСТ (Кузнечик/Магма для страниц/WAL/аудита) и переход контрольных сумм/SCRAM на Стрибог — roadmap, не реализованы. Эта страница — про настройку и проверку именно GOST-TLS.
Аудитория: специалисты по безопасности, DevOps, QA.
1. GOST в AngaraBase: что есть и что планируется
1.1. Транспорт (TLS) — доступно
Защита данных в канале на ГОСТ Р 34.10-2012 (открытый ключ) и наборах шифров ГОСТ 28147-89.
- Реализация: провайдер-абстракция (OpenSSL Engine / Rustls).
- Политика: fail-closed — сервер откажется стартовать, если настроенный GOST-провайдер недоступен.
- Конфиг:
tls.gost_enabled,tls.gost_cipher_suites.
1.2. Данные на диске (TDE) — planned
Шифрование страниц, WAL и журналов аудита блочными шифрами Кузнечик (ГОСТ 34.12-2015) или Магма — пункт roadmap. Управление ключами через внешний KMS с поддержкой ГОСТ. Сейчас не реализовано.
⚠️ Серверный TDE в текущих версиях использует XOR-keystream, а не ГОСТ-шифр и не AES/AEAD. См. Шифрование.
1.3. Целостность и аутентификация — future
Переход контрольных сумм и SCRAM с SHA-256 на Стрибог (ГОСТ Р 34.11-2012) и цифровая подпись журналов аудита — планы, не реализованы.
2. Тестирование GOST-TLS
Как убедиться, что AngaraBase действительно использует ГОСТ-наборы и строго соблюдает fail-closed.
Предусловия
Нужна Linux-среда с OpenSSL, настроенным под ГОСТ.
# Debian/Ubuntu
sudo apt-get install openssl libssl-dev libengines-gost
# Проверка доступности движка
openssl engine gost -t
# В выводе должно быть: [gost] Reference implementation of GOST engine -> [ available ]
Шаг 1. Сгенерировать ГОСТ-сертификаты
Обычные RSA/ECDSA-сертификаты не подойдут к ГОСТ-наборам — ключи нужно сгенерировать ГОСТ-алгоритмами.
# 1. Приватный ключ по ГОСТ Р 34.10-2012 (256 бит)
openssl genpkey -algorithm gost2012_256 -pkeyopt paramset:A -out gost_server.key
# 2. Самоподписанный сертификат
openssl req -new -x509 -days 365 \
-key gost_server.key \
-out gost_server.crt \
-subj "/CN=localhost"
# 3. Проверить алгоритм сертификата
openssl x509 -in gost_server.crt -text -noout | grep "Signature Algorithm"
# Ожидается: Signature Algorithm: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)
Шаг 2. Настроить AngaraBase
Включить TLS и ГОСТ-режим. Чтобы проверить строгий режим, убедитесь, что
allow_insecure выключен.
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"
./angarabase-server --config-path ./angarabase.conf
tls.gost_enabled по умолчанию выключен (явный opt-in); дефолтный набор —
GOST2012-GOST8912-GOST8912:GOST2001-GOST89-GOST89.
Шаг 3. Позитивная проверка
Подключитесь клиентом с поддержкой ГОСТ (например, openssl s_client или
пропатченный psql).
openssl s_client -connect localhost:5152 -servername localhost
Чек-лист:
- В выводе есть
Cipher : GOST2012-GOST8912-GOST8912(или другой ГОСТ-набор). Protocol : TLSv1.2.- Handshake завершается успешно.
Через SQL (если клиент поддерживает):
SELECT name, value FROM sys.settings WHERE name LIKE 'tls.%';
-- Проверьте, что tls.gost_enabled = 'true'
Шаг 4. Проверка fail-closed (негативные тесты)
Убедитесь, что сервер отказывается стартовать при сломанном окружении.
- Нет провайдера. Временно отключите ГОСТ-движок (переименуйте библиотеку
или измените конфиг OpenSSL) и запустите с
ANGARABASE_TLS_GOST_ENABLED=1. → Ожидается: отказ старта с «GOST provider not available». - Невалидный набор шифров.
ANGARABASE_TLS_GOST_CIPHER_SUITES="INVALID-CIPHER". → Ожидается: отказ старта с ошибкой конфигурации. - RSA-сертификат с ГОСТ-наборами.
ANGARABASE_TLS_GOST_ENABLED=1, но обычные RSA-сертификаты. → Ожидается: провал handshake («no shared cipher» / «wrong signature type»).
3. Диагностика
| Симптом | Вероятная причина | Решение |
|---|---|---|
no shared cipher | клиент без ГОСТ или у сервера RSA-сертификаты | поставьте libengines-gost на клиенте; ГОСТ-сертификаты на сервере |
wrong signature type | несовпадение типа ключа сертификата | используйте gost2012_256 при генерации ключа |
| Сервер не стартует | openssl.cnf не настроен под ГОСТ | проверьте openssl engine gost -t |
Дальше
После того как вы определились, какие 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
Конфигурация
Настройка инстанса AngaraBase для локального теста или production: ключи
TOML-конфига, директории данных и переопределения через переменные окружения.
Нужен собранный angarabase-server (см. Quickstart).
Минимальный конфиг
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:9899" # Admin TCP API (remote backups via angara-cli --addr); empty = disabled
Журнал транзакций (durability)
[transaction_log]
backend = "file_bin" # durable binary WAL; нужен для crash-recovery MVCC
durability = "strict" # strict | relaxed | group_commit
fsync = true
Компилируемый дефолт
backend—noop(без durability, для ephemeral/тестов). Для любого реального инстанса ставьтеfile_bin— только с ним работает восстановление MVCC после аварии (см. Crash recovery).
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
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
Инициализация
Перед первым обычным запуском выполните --init:
angarabase-server --config-path /path/to/angarabase.conf --init
- Каталоги
data_directoryиtransaction_log_directoryдолжны быть доступны на запись. - При заданном
logging.log_directoryсервер пишетangarabase-server.log. --initсоздаёт все необходимые артефакты каталога данных (см. ниже).
Шорткаты для dev/test — в Quickstart.
Артефакты каталога данных
Внутри storage.data_directory сервер создаёт и поддерживает:
| 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.
Переменные окружения
Переменные окружения переопределяют соответствующие ключи конфига; если заданы оба — выигрывает переменная окружения.
Приоритет: default → config → env override
Все параметры можно задать в angarabase.conf. Переменные окружения нужны для
оперативного переопределения и диагностики; для постоянной конфигурации
используйте TOML-файл. Эффективные значения и их источник видны в sys.settings.
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. |
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).
Ожидаемый результат
После успешного --init и запуска:
curl -sS http://127.0.0.1:9898/health/ready # порт совпадает с [ops].metrics_addr
Возвращает {"status":"ready"}. Эффективная конфигурация видна через:
SELECT * FROM sys.settings;
Диагностика
| Симптом | Действие |
|---|---|
| Сервер не стартует в trust-режиме | добавьте --allow-insecure-no-auth |
Несовпадение VERSION при старте | каталог данных инициализирован другой версией сервера — переинициализируйте или обновитесь |
| TDE fail-closed после restore | обеспечьте тот же ключ (ANGARABASE_TDE_MASTER_KEY_HEX) |
| Параметр не применился | проверьте приоритет: env переопределяет config; смотрите SELECT * FROM sys.settings (значения и источники) |
Нерешённое — в Известных ограничениях и Поддержке.
См. также
- Security operations baseline — security/ops-кнобы,
fail-closed гейты, контракт
sys.settings. - Диагностика — анализ производительности запросов.
- 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:
Скрипт поднимает контейнер из канонического 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 -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 вместо прямых вызовов dev-скриптов:
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 режиму см.
docs/gtm/PILOT_CHECKLIST.md(§5 и §6).
Backup and restore
Резервное копирование и восстановление инстанса AngaraBase — от холодного (offline) бэкапа до онлайн-цепочки FULL + LOG с восстановлением на момент времени (PITR).
Требуется инициализированный инстанс и бинарь angara-cli. Для онлайн-бэкапа —
запущенный сервер с WAL ([transaction_log] backend = file_bin, не noop).
Какой способ выбрать
| Сценарий | Способ |
|---|---|
| Перенос инстанса на другой хост, есть окно простоя | Host migration — копирование файлов, без бэкапа |
| Базовый offline-снимок одним файлом | phase 1a: backup full → *.angarabk |
| Онлайн-бэкап без остановки + PITR на произвольный LSN | phase 1b: full-online + log + restore-chain |
| Бэкап с центрального узла без SSH к БД | любой из выше — через Admin API (--addr) |
Для новых развёртываний по умолчанию — phase 1b (онлайн + PITR). Phase 1a — когда достаточно простого offline-снимка. Legacy shell-обёртки оставлены для совместимости.
Флаг конфигурации у angara-cli — --config / -c (у angarabase-server —
--config-path); для удалённого выполнения через Admin API вместо --config
указывается --addr <host:port>.
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:
Restore:
Oracle (post-restore verification):
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
angarabase-serverдолжен быть запущен с включённым Admin API ([ops] admin_addrвangarabase.confили переменнаяANGARABASE_ADMIN_ADDR; если адрес не задан, admin-листенер не поднимается).angara-cliзапускается с--addr <host:port>вместо--config.- Нужен сетевой доступ к порту Admin API (по умолчанию
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)
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)
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-path /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
См. также
- Конфигурация — TDE-ключи,
[ops] admin_addr, backend WAL. - Диагностика — health-check после restore.
- Crash recovery — детали host migration.
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 bundled AngaraBase overview dashboard JSON (see the download step below).
- 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_query_exec_total |
| Query latency p50/p95/p99 | histogram buckets |
| Slow query count | angarabase_slow_query_total |
| Active connections | gauge |
| TPS / commit latency | angarabase_txn_commit_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: -
For further investigation see Diagnostics and Support.
Links
- Dashboard JSON from server:
GET /grafana/angarabase-overview.json(onANGARABASE_METRICS_ADDR/[ops].metrics_addr) - 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
- Operator runbook:
angarabook/src/operations/troubleshooting.md - Инцидентный runbook (10 минут): Error debug runbook
- Support flow: Support
Логирование
AngaraBase пишет структурированные логи через tracing / tracing_subscriber
(формат key=value), пригодные для систем агрегации (ELK, Splunk и т.п.).
Уровни
| Уровень | Когда | Примеры |
|---|---|---|
error | сбои системы, неустранимые ошибки | повреждение данных, OOM, восстановление после паники |
warn | восстановимые сбои, деградация, мисконфигурация | отказ heartbeat, ошибки audit-sink, fallback-режимы |
info | операционные события, смена состояния | старт инстанса, захват аренды, завершение сбора статистики |
debug | детальная диагностика, внутреннее состояние | прогресс micro-rescan, детали MVCC-recovery, статистика buffer pool |
trace | очень подробно, горячий путь | обработка отдельных кортежей, захват блокировок |
Рекомендации: info — в production; debug — на время разбора инцидента;
trace — только в разработке.
Управление уровнем
Уровень и фильтр задаёт переменная окружения RUST_LOG (читается на старте,
по умолчанию info). Поддерживается синтаксис EnvFilter — в т.ч. фильтры по
модулям:
# глобальный уровень
RUST_LOG=debug ./angarabase-server --config-path /etc/angarabase/angarabase.conf
# по модулям: debug для сервера, warn для TLS
export RUST_LOG="angarabase_server=debug,rustls=warn"
./angarabase-server --config-path /etc/angarabase/angarabase.conf
Фильтр фиксируется при запуске — чтобы изменить уровень, перезапустите сервер с
новым RUST_LOG.
Настройка
logging.log_level(envANGARABASE_LOG_LEVEL, конфиг[logging]) валидируется и видна вsys.settings, но консольный subscriber слушает именноRUST_LOG. Для фактического изменения вербозности сервера используйтеRUST_LOGи перезапуск.
-- посмотреть записанное значение настройки
SELECT name, value FROM sys.settings WHERE name = 'logging.log_level';
Формат строки
2026-03-09T10:30:45.123Z INFO angarabase_server::stats stats_scheduler: auto_analyze_triggered table=users staleness_score=2.45
- Timestamp — ISO 8601, миллисекунды.
- Level — ERROR/WARN/INFO/DEBUG/TRACE.
- Module — путь модуля Rust (например,
angarabase_server::stats). - Context — структурированные пары
key=valueс префиксом операции (например,instance_lease:,micro_rescan:). Чувствительные данные в логи не попадают — только идентификаторы.
Production
Ротация (logrotate)
# /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
}
Агрегация
ELK (logstash):
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-operation = (?<operation>\w+):
Полезные грепы
grep "ERROR" /var/log/angarabase/server.log | wc -l # частота ошибок
grep "instance_lease.*failed" /var/log/angarabase/server.log
grep "mvcc_recovery:" /var/log/angarabase/server.log
Влияние на производительность
| Уровень | Накладные расходы |
|---|---|
error/warn | минимальные — безопасно в production |
info | низкие — уровень по умолчанию |
debug | умеренные — на короткое время для разбора |
trace | высокие — только разработка |
См. также
- Tracing — распределённая трассировка (spans, OTLP).
- Мониторинг — метрики Prometheus.
- Жизненный цикл инстанса — события аренды в логах.
- Crash recovery — логи восстановления MVCC.
Tracing
AngaraBase использует tracing. Есть два уровня наблюдаемости:
- Логи сервера — вербозность задаёт
RUST_LOG(см. Логирование). - Трассы запросов (OTel-спаны) — опциональный per-query экспорт спанов
accept → parse → plan → execute → storage → commit.
Экспорт идёт только в stderr (через лог) или в локальный JSONL-файл. Сетевого OTLP-коллектора, Jaeger/Tempo, push по HTTP — нет.
Включение трасс запросов
Per-query трассы выключены по умолчанию. Управление — переменными окружения:
| Переменная | Назначение | По умолчанию |
|---|---|---|
ANGARABASE_OTEL_ENABLED | включить экспорт спанов (1/true/yes/on) | off |
ANGARABASE_OTEL_SAMPLE_RATE_PPM | доля сэмплируемых запросов в ppm (0 — выкл, 1000000 — 100%) | 1000000 |
ANGARABASE_OTEL_EXPORTER | приёмник: stderr или file | stderr |
ANGARABASE_OTEL_ENDPOINT | путь к JSONL-файлу (только при EXPORTER=file) | — |
# 5% запросов в локальный JSONL-файл
export ANGARABASE_OTEL_ENABLED=1
export ANGARABASE_OTEL_SAMPLE_RATE_PPM=50000
export ANGARABASE_OTEL_EXPORTER=file
export ANGARABASE_OTEL_ENDPOINT=/var/log/angarabase/query-traces.jsonl
./angarabase-server --config-path /etc/angarabase/angarabase.conf
При EXPORTER=stderr строки спанов попадают в обычный лог сервера (на уровне
info).
Что в спане
Каждая трасса запроса несёт идентификаторы, по которым её можно связать с
sys.*-диагностикой:
- логическая БД и пользователь;
- класс запроса (
QueryClass); queryidиplanid(если доступны) — те же идентификаторы, что вangara_stat_statementsиEXPLAIN.
Разбор JSONL
# медленные запросы (>1s) из файла трасс
jq 'select(.duration_ms > 1000)' /var/log/angarabase/query-traces.jsonl
# распределение по queryid
jq -r '.queryid' /var/log/angarabase/query-traces.jsonl | sort | uniq -c | sort -rn | head
Для агрегатных метрик (latency-перцентили, частота медленных запросов) используйте Prometheus-эндпоинт — см. Мониторинг, а для точечного анализа плана — Диагностику.
Безопасность
⚠️ Спаны и логи могут содержать текст SQL с чувствительными данными.
- Ограничьте доступ к файлу трасс:
chmod 640, владелец — сервисный пользователь. - Настройте ротацию (см. logrotate в Логировании).
- Не включайте 100%-сэмплинг с текстом SQL на проде без необходимости — это и объём, и риск утечки.
Если трасс нет
ANGARABASE_OTEL_ENABLEDне установлен в1/true— спаны не пишутся.ANGARABASE_OTEL_SAMPLE_RATE_PPM=0— сэмплинг выключен.EXPORTER=file, ноANGARABASE_OTEL_ENDPOINTне задан или путь недоступен на запись — строка уходит в stderr-лог вместо файла.- Слишком строгий
RUST_LOGдля stderr-экспортёра — поднимите уровень (см. Логирование).
См. также
- Логирование —
RUST_LOG, формат строк, ротация, агрегация. - Мониторинг — метрики Prometheus.
- Диагностика —
EXPLAIN,angara_stat_*, медленный лог.
USDT / eBPF probes
AngaraBase встраивает USDT-пробы (User Statically-Defined Tracing) — точки инструментации для eBPF-инструментов (bpftrace, bcc, perf).
- Zero-overhead, пока не подключён трейсер: в бинаре это NOP-инструкции.
- Без рестарта: трейсер цепляется к работающему процессу.
- Провайдер —
angarabase; пробы компилируются с featureusdt(включён по умолчанию). Сборка--no-default-featuresих исключает.
Проверка наличия проб
# пробы встроены?
readelf -n ./angarabase-server | grep -A5 stapsdt
# список доступных проб
bpftrace -l 'usdt:./angarabase-server:angarabase:*'
Теги запросов (query_tag)
Каждая проба несёт tag — u64-хеш (xxh64) метки запроса. По умолчанию 0
(нетегированный трафик; operator_*-пробы для него вообще не срабатывают). Тег
позволяет фильтровать только интересующие запросы.
-- на сессию:
SET query_tag = 'demo-heavy-report';
RESET query_tag;
-- на отдельный запрос (hint в комментарии):
/*+ angarabase:tag=demo-heavy-report */ SELECT * FROM orders;
В bpftrace фильтр /* tag */ != 0 оставляет только тегированный трафик.
Сигнатуры основных проб
Аргументы в bpftrace — arg0, arg1, … в порядке ниже.
| Проба | Аргументы |
|---|---|
query_start | session_id u64, query_fingerprint u64, tag u64 |
query_end | session_id, query_fingerprint, total_us, outcome u8, tag, rows |
phase_start | session_id, phase u8, tag |
phase_end | session_id, phase u8, duration_us, tag |
lock_wait_start | session_id, lock_type u8, tag, resource_id |
lock_wait_end | session_id, wait_us, tag |
io_start | session_id, op_type u8, bytes u32, tag, table_id u32 |
io_end | session_id, latency_us, tag |
operator_start | session_id, tag, operator_type u8, table_id u32 (только tag≠0) |
operator_end | session_id, tag, operator_type u8, rows_out, duration_us (только tag≠0) |
Энумы (append-only):
phase:0=parse,1=plan,2=execute,3=commitoutcome:0=Ok,1=Error,2=Timeout,3=Cancelledlock_type:0=Row,1=Page,2=Table,3=Transactionop_type(io):0=PageRead,1=PageWrite,2=WalFlush,3=Fsync
Помимо них есть расширенные группы проб (тот же провайдер): net_stall_*,
sched_wait_*, parallel_*, vector_batch_* / vector_fallback,
io_uring_*, optimizer_plan_*, qos_enqueue / qos_reject,
write_phase_b_*, fsync_timeout. Полный список — командой bpftrace -l выше.
Примеры bpftrace
Латентность запросов
bpftrace -e '
usdt:./angarabase-server:angarabase:query_end {
$duration_us = arg2; // total_us
$outcome = arg3; // 0 = Ok
if ($outcome == 0) { @latency_us = hist($duration_us); }
else { @failed++; }
}
interval:s:5 { print(@latency_us); printf("failed: %d\n", @failed); clear(@failed); }'
Тайминг по фазам
bpftrace -e '
usdt:./angarabase-server:angarabase:phase_end {
$phase = arg1; $us = arg2; // phase: 0=parse 1=plan 2=execute 3=commit
@by_phase[$phase] = hist($us);
}
interval:s:10 { print(@by_phase); }'
Контеншн блокировок
bpftrace -e '
usdt:./angarabase-server:angarabase:lock_wait_end {
$wait_us = arg1;
@lock_wait = hist($wait_us);
if ($wait_us > 1000) { printf("SLOW LOCK: session=%d wait=%dus\n", arg0, $wait_us); }
}
interval:s:5 { print(@lock_wait); }'
Только тегированный трафик (по тегу)
bpftrace -e '
usdt:./angarabase-server:angarabase:lock_wait_end /arg2 != 0/ { @lock_us_by_tag[arg2] = hist(arg1); }
usdt:./angarabase-server:angarabase:io_end /arg2 != 0/ { @io_us_by_tag[arg2] = hist(arg1); }'
Безопасность
- Для подключения eBPF нужны привилегии:
sudo setcap cap_bpf+ep /usr/bin/bpftraceили запуск от root. - Пробы могут раскрывать поведение запросов; ограничьте доступ к bpftrace отдельной группой.
Если проб нет
- Бинарь собран с
--no-default-features(пробы исключены) — пересоберите со стандартными feature. - Неверный путь к бинарю в
usdt:<path>:angarabase:*. - Нет привилегий BPF (см. выше) или несовместимое ядро.
См. также
- Tracing — OTel-спаны запросов в stderr/JSONL.
- Мониторинг — метрики Prometheus.
- Диагностика —
EXPLAIN,angara_stat_*, медленный лог.
GC auto-tuning
AngaraGC автоматически подстраивает бюджет сборки мусора под нагрузку по телеметрии:
- Bloat ratio — сколько мёртвых данных накопилось;
- Epoch lag — насколько активные транзакции отстают от закоммиченного состояния;
- Cycle latency — сколько длится цикл GC.
Контроллер использует обратную связь, балансируя агрессивную очистку (высокий бюджет) против влияния на латентность (низкий бюджет).
Включение
export ANGARABASE_GC_BACKGROUND=1 # фоновый GC-воркер
export ANGARABASE_GC_AUTO_TUNING=1 # контроллер авто-тюнинга
Или через конфиг ([gc] auto_tuning включён по умолчанию):
[gc]
auto_tuning = true
Цели контроллера фиксированы (заданы в реализации, не настраиваются):
bloat-target ≈ 20%, epoch-lag-target ≈ 1000, порог скачка латентности ≈ 100 мс,
границы бюджета 100..100000 строк/цикл, sleep 10..1000 мс. Контроллер никогда
не выходит за min/max бюджета.
Наблюдаемость
SELECT * FROM sys.gc_tuning_status;
Колонки:
current_budget— текущий бюджет GC (строк/цикл);sleep_ms— текущая пауза между циклами;tuning_decision— последнее решение (increase/decrease/hold).
Метрики Prometheus:
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
angarabase_gc_tuning_decision_total_increase
angarabase_gc_tuning_decision_total_decrease
angarabase_gc_tuning_decision_total_hold
Когда включать
- Переменная нагрузка — авто-тюнинг адаптируется к изменениям.
- Высокий риск bloat — поднимает бюджет при накоплении мёртвых версий.
- Латентность-чувствительные нагрузки — снижает бюджет при скачках задержки.
Когда не нужно: предсказуемая нагрузка со стабильным бюджетом (проще
статический режим — выключите авто-тюнинг и задайте фиксированный бюджет в
[gc]); либо при отладке GC, чтобы изолировать поведение фиксированным бюджетом.
Диагностика
Авто-тюнинг осциллирует (tuning_decision быстро чередует
increase/decrease): контроллер самокорректируется; если осцилляция устойчива,
отключите авто-тюнинг (ANGARABASE_GC_AUTO_TUNING=0) и используйте статический
бюджет.
Бюджет «залип» на min/max (current_budget упёрся в границу):
- на максимуме — bloat/lag устойчиво выше цели → разберитесь с нагрузкой;
- на минимуме — устойчивые скачки латентности → ищите GC-контеншн или снизьте объём GC-работы.
Дальше
После того как gc.auto_tuning включён и метрики 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.enabled | 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
Check the negotiated cipher with openssl s_client (AngaraBase does not implement
SHOW ssl_cipher):
openssl s_client -connect localhost:5152 -servername localhost </dev/null 2>/dev/null \
| grep -E 'Cipher|Protocol'
The Cipher line should show a GOST suite (e.g. GOST2012-GOST8912-GOST8912).
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 (0.6.3.8 S7) | Per-alert remediation: backing pages для каждого runbook_url в наборе Prometheus alert rules |
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 правила из набора Prometheus
alert rules (0.6.3.8 S7).
Каждый alert содержит annotations.runbook_url со ссылкой на одну из
страниц ниже — это binding между observability surface и operator
remediation path.
По 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
Backed by: 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 (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
Backed by: 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
Backed by: 0.6.3.8 S7. Renamed from
HighErrorRateв 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, перенесено в 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 (0.6.6.0 Specs Backlog)
Runbook: BufferPoolPressure
Backed by: 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
# Текущая ёмкость и загрузка буферного пула (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
-
Авто-сайзинг (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 (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 (0.6.3.9 §S2+§S8 capacity waiter). - Resource Advisors v0 (0.6.3.9 §S10) —
angarabase_memory_pressure_ratiocorrelates with sustainedBufferPoolPressureevents when working-set growth, not churn, is the cause.
Runbook: WALFsyncSlow
Backed by: 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:
- 0.6.3.10 (Track B S11/S12/S13) — group-commit baseline.
- 0.6.4.0 (Sprint 2/3) — WAL contract, SyncAtCommit mode.
Что означает
Runbook для ситуации, когда COMMIT latency выше ожидаемой либо нестабильна между одинаковыми нагрузками (single-client cron jobs, batch DML, mixed RW).
После 0.6.4.0 введён режим sync_at_commit (alias strict): каждый COMMIT
принудительно fsync-ирует WAL перед подтверждением. Это добавляет новые режимы
в таблицу ожидаемых latency.
Режимы durability (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 существенно выше диапазона, проверяй диагностический блок ниже.
Какие метрики смотреть
Новые метрики 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 метрики (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
Backed by: 0.6.3.8 S7, 0.6.4.4 (SSI).
Что означает
rate(angarabase_deadlock_detected_total[1m]) > 1 — детектор deadlock’ов
сработал чаще одного раза в минуту. Один-два deadlock’а в час — нормально;
spike указывает на проблемный workload pattern.
Для SERIALIZABLE транзакций: всплеск ошибок 40001 (serialization_failure)
может выглядеть как deadlock spike в логах приложения, но имеет другую природу
(rw-антизависимости). Аборты сериализации (40001) видны в метрике angarabase_txn_commit_conflicts_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
Backed by: 0.6.3.8 S7, 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
Backed by: 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
Backed by: 0.6.3.8 S7.
Что означает
Задержка реплики (angara_replication_lag_bytes) велика и растёт.
Реплика отстаёт от 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
# Лаг в байтах (PG-функция pg_last_xact_replay_timestamp в AngaraBase не реализована)
curl -sf http://replica:9898/metrics | rg angara_replication_lag_bytes
См. также 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
Backed by: 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, - инвариант per-DB co-location страниц нарушен.
Severity
warning. Не critical — данные не теряются и индекс работает, но требует миграции.
Why this alert fires after upgrade
0.6.3.8 ввёл per-DB IndexStore page routing. Бинарь до 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
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-path /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 (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 (0.6.6.5)
- Агрегатные функции
SUM(float4)иSUM(float8)автоматически используют SIMD инструкции (AVX2 или NEON) при наличии поддержки процессором. - Это значительно ускоряет аналитические запросы над числами с плавающей точкой.
- Если SIMD недоступен, система прозрачно переходит на скалярную реализацию, инкрементируя метрику
angarabase_simd_agg_fallback_total.
Adaptive Hash-Join (0.6.6.5)
- Планировщик автоматически меняет местами стороны Build и Probe в Hash Join по их относительному размеру — для построения хэш-таблицы берётся меньшая сторона.
- Это экономит память и снижает вероятность сброса на диск (spill).
- Поведение эвристическое и не настраивается отдельным кнобом.
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, 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(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) в конфиге и перезапустите процесс.
- Если селективность не ниже этого порога, индексный скан также отклоняется (
LateMaterialize(отложенная материализация колонок) и адаптивный swap сторон Hash Join применяются планировщиком автоматически по эвристике — отдельных настраиваемых порогов для них нет.- Перечисленные
[execution]-пороги меняются только через файл конфигурации (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. Это позволяет избежать дорогого чтения всех колонок для строк, которые всё равно будут отфильтрованы.
Порог включения (≈ 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 (0.6.5.20)
С 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 файла
Используй после bulk DELETE / большого числа UPDATE, если .adb файл подозрительно большой.
Index GC (Background Sweep)
В 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 (0.6.6.11)
С 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 (0.6.6.11)
Для колоночных (tiered columnar) таблиц с 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)
Дополнительно к фоновому воркеру, в 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):
С конфигом и директориями:
Валидация структуры:
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: security-relevant knobs в едином операционном
контракте — безопасные дефолты, fail-closed гейты, точки наблюдаемости
(sys.settings).
Источники
- Configuration schema reference — полная схема конфигурации.
- Operational policies baseline — governance безопасности.
- Рантайм-поверхность настроек видна через
sys.settings.
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(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 — в Operational policies baseline.
Дальше
- 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):
Restore oracle (txlog-level):
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)
Для packaged distribution (apt install angarabase-server) предпочтителен angara-cli (remote admin over TCP
or local). Legacy dev-скрипт остаётся только для dev/workspace.
Remote admin flow:
angara-cli backup ... --remote-admin(или через configured admin endpoint).- Runbooks в
angarabook/src/operations/теперь ссылаются на packaged CLI вместо прямого вызова dev-скриптов.
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 (0.6.5.6)
Начиная с 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 (0.6.5.8)
-
[wal] max_size_mb: Максимальный размер сегментов WAL. Применяется с 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 (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 (0.6.5.8)
-
Index Durability: Начиная с 0.6.5.8, операция
CREATE INDEXгарантирует долговечность (durability). После завершения команды индекс полностью синхронизирован и доступен после восстановления (recovery) даже в случае сбоя сразу после создания. -
storage.index_maintenance_budget_ms(default: 5000, envANGARABASE_INDEX_MAINTENANCE_BUDGET_MS): бюджет времени на поддержку индексов в одной DML-команде; превышение →MaintenanceBudgetExceeded, DML откатывается.
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 (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 0.6.4.2 Surface Map 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 (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 (0.6.6.8)
В 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_server_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_server_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 по БД, 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{outcome="ok",class="select"} | counter | SELECT queries OK | — | QPS baseline |
angarabase_query_exec_total{outcome="ok",class="write"} | counter | Write queries OK | — | Write TPS |
angarabase_query_exec_total{outcome="err",class="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{outcome="ok",class="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 (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 (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 (0.6.5.8)
| Метрика | Тип | Смысл |
|---|---|---|
angarabase_checkpoint_total | counter | Общее число выполненных чекпоинтов. > 0 после 5 мин uptime подтверждает работу auto-checkpoint. |
Visibility Map and Index-Only Scan (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».
Новые метрики 0.6.4.0 (WAL Commit-Path + Durability)
Добавлены в Sprint 2/3 0.6.4.0. Покрывают новый режим 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).
HTAP / Vector Execution Metrics (0.6.4.13 / 0.6.4.14 / 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-пути (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 (0.6.7.15). |
Примечание: метки
reason=уangarabase_scan_stream_materialize_total— стабильный оператор-facing контракт в рамкахv0.6.x.
Columnar DV Pressure (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 (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 (0.6.4.10 / 0.6.4.19)
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 (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 (0.6.5.10)
angarabase_query_exec_duration_ms — histogram задержки выполнения SQL-запросов.
Note (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). |
Метрики статистики (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. |
Метрики vector-пути: NUMERIC float-backed и columnar grouped-agg
Две operator-facing counter-метрики, добавленные в 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 | Legacy-сигнал старого lossy float-backed numeric-пути. С 0.6.7.16 всегда 0 (numeric теперь exact Decimal, см. ниже). |
angarabase_vector_columnar_grouped_agg_total | counter | Количество раз, когда GROUP BY-агрегат был выполнен колоночным hash-agg путём (а не через row-fallback). Path-signal. |
angarabase_vector_numeric_float_backed_total
Что значит. Это legacy-сигнал. В версиях до 0.6.7.16 numeric(p,s>0) /
decimal(p,s>0) на vector-пути проецировались в физический Float64 (lossy —
риск потери точности в SUM/AVG над денежными колонками).
Начиная с 0.6.7.16 этот lossy-путь убран: появился точный Decimal
(NUMERIC/DECIMAL Phase 0), и numeric на vector-пути теперь делает row-fallback
к точному Decimal, а не лоссит во Float64. Поэтому счётчик постоянно 0 —
метрика сохранена для обратной совместимости дашбордов.
Для точности денежных вычислений отдельных обходных путей больше не нужно — используйте обычный
NUMERIC(p,s). Контроль точного decimal — метрикиangarabase_decimal_overflow_total,angarabase_decimal_legacy_floatread_total(см. Тип NUMERIC/DECIMAL).
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, 0.7.7.1).
Эквивалентность результата колоночного пути row-fallback подтверждена AC-тестами 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)
0.6.7.16. Начиная с этого релиза
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.
Метрики (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: 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 (0.6.4.0)
SELECT table_name, storage_engine
FROM sys.tables
WHERE table_name = 'metrics';
Фоновая компактизация (L1 Compaction)
Начиная с 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, 0.6.4.0)
- SegmentManifest auto-init при создании таблицы — deferred to Sprint 4 (OQ-S3-3).
- OOM protection для Column Cache — Sprint 4 (OQ-S3-4).
- Полная AP-оптимизация сканов — Phase 2.
Связанные
- Performance tuning guide — tuning для mixed OLTP+HTAP нагрузок.
- Observability metrics — метрики columnar store.
Wait Events
AngaraBase 0.6.3.9 §S11 — базовая модель wait events. 0.6.4.10 добавляет QoS scheduler events. 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 события 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 (0.6.4.19 Track C C1)
Начиная с 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_dirty_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
Resource Advisors v0
AngaraBase 0.6.3.9 §S10 — single-node, in-process advisors. Closes the Article #5 review finding on advisor ↔ 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 (0.7.0 / 0.8.0); 0.6.3.9 promotes only the
single-node sensor stubs previously called out as [Future] 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. 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 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 (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 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 (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 notes for 0.6.3.9 contain the migration note.OPERATOR-UX hardening (2026-04-20, 0.6.3.10, closes F-UX-1 + OQ-2026-054): 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 | angarabase_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 §7a Observability Contract that was deferred from 0.6.2.9 G2 (Sprint 4 G2-001 disposition). User direction 2026-04-20 «extended scope» — close before the HTAP column-store train (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. This page
covers only the vector-executor-specific subset of the broader USDT/eBPF probe
infrastructure, 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. The broader probe taxonomy was still 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 ship with the workspace USDT tooling (per the standing
convention — 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 |
|---|---|
0.6.3.10 §S17 | Sprint contract (this page is the operator-facing rendering) |
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:9898/metrics | rg jemalloc # порт = [ops] metrics_addr
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:
- длительная нагрузка
Сравниваются baseline/after по allocated/resident/mapped и fragmentation.
Related references
src/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 (провайдер
angarabase): parallel_scan_start/parallel_scan_end(workers_planned/launched, morsels)parallel_agg_merge_start/parallel_agg_merge_endparallel_worker_cancel,parallel_budget_exceeded- 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 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.
Client Compatibility Baseline
Операторский baseline по совместимости клиентов/ORM.
Каноничный источник: этот runbook в angarabook/src/operations/.
Supported Framework Matrix (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
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 (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 (0.6.5.5)
UPDATE SET col = func_call(): Теперь поддерживается использование функций (например,write_date = NOW()) и явных приведений типов (col = val::type) в клаузеSET. Это критично для Odoo 19.
Query Execution & Bug Fixes (0.6.5.7)
- Bool comparison: Сравнение констант разных типов теперь корректно приводится к boolean.
Пример:
SELECT 1 = 2;возвращаетf(ранее могло вызывать ошибку типов).
Поддерживаемые типы (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 (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 (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 (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 командой.
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 (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) for AngaraBase via subscriptions over a table’s change log.
API
-- create a subscription on a table's DML events
CREATE SUBSCRIPTION "my-sub" ON TABLE public.orders
FOR EVENTS (INSERT, UPDATE, DELETE)
WITH (start_offset = 'latest');
-- poll up to N events (does NOT advance the cursor)
SELECT * FROM angara_stream_poll('my-sub', batch_size => 100);
-- acknowledge up to an offset (advances the cursor)
SELECT angara_stream_ack('my-sub', offset => 42);
-- remove the subscription
DROP SUBSCRIPTION "my-sub";
FOR EVENTS (...) may list any subset of INSERT/UPDATE/DELETE; an empty
list defaults to all three.
start_offset semantics
The start_offset WITH-option controls which events a new subscription sees.
| Value | Behaviour |
|---|---|
'latest' (default) | Skips history. Only events published after the subscription is created are delivered. |
'earliest' | Delivers events currently retained in the buffer, starting from the oldest retained event. |
The change-log buffer is bounded: events older than the retained window have
already been evicted and are not delivered even with 'earliest' — the cursor
starts at the oldest event still in the buffer. For a full re-seed you must drop
and recreate the subscription (and reload the table out of band):
DROP SUBSCRIPTION "my-sub";
CREATE SUBSCRIPTION "my-sub" ON TABLE public.orders
FOR EVENTS (INSERT, UPDATE, DELETE)
WITH (start_offset = 'earliest');
SQLSTATE
| Situation | SQLSTATE |
|---|---|
CREATE SUBSCRIPTION of an existing name | 42710 (duplicate_object) |
| Poll/ack/drop of a non-existent subscription | 42704 (undefined_object) |
| Invalid subscription name | 42602 (invalid_name) |
| Malformed statement | 42601 (syntax_error) |
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 (0.6.6.8)
В версии 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 (0.6.6.13)
В рамках 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).
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 поддерживает декларативное партицирование: 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, CI, harnesses): утилиты, runners, тестовые harness’ы. - Distribution/Packaging tooling (packaging, release scripts): 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, CI, harnesses)] 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
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и почему.
Error Codes Reference
AngaraBase uses an internal EngineErrorKind enum as the single source of truth for error codes.
At the protocol boundary, engine errors are translated to PostgreSQL SQLSTATE codes via the ERROR_REGISTRY.
Error Categories
| Category | Description |
|---|---|
InvalidInput | Client passed invalid parameters or malformed query |
TransactionControl | Transaction state errors (serialization failures, conflicts) |
AccessControl | Insufficient privileges |
ResourceLimit | Resource exhaustion (memory, connections, locks) |
InternalError | Internal engine errors (bugs, invariant violations) |
IoError | Disk/network I/O errors |
Error Code Registry
| EngineErrorKind | PG SQLSTATE | PG Code Name | Category | Description |
|---|---|---|---|---|
InvalidParameter | 22023 | invalid_parameter_value | InvalidInput | Caller passed an invalid parameter (validation failure inside the engine). |
TransactionAborted | 40001 | serialization_failure | TransactionControl | Transaction aborted by the engine (serialization failure, conflict, …). |
LockTimeout | 55P03 | lock_not_available | ResourceLimit | Lock acquisition exceeded the configured timeout. |
AccessDenied | 42501 | insufficient_privilege | AccessControl | Authorization / RBAC denial inside the engine. |
InternalError | XX000 | internal_error | InternalError | Catch-all internal error (unexpected state, broken invariant). |
DuplicateKey | 23505 | unique_violation | InvalidInput | Unique-key violation (catalogued for clean SQLSTATE mapping). |
ConstraintViolation | 23000 | integrity_constraint_violation | InvalidInput | Generic constraint violation (FK, CHECK, NOT NULL, …). |
NotFound | 42704 | undefined_object | InvalidInput | Object does not exist (table, schema, row, …). |
IoError | 58030 | io_error | IoError | I/O error from storage / WAL / recovery layer. |
ResourceExhausted | 53000 | insufficient_resources | ResourceLimit | Resource exhaustion (memory limits, connection limits, …). |
QosQueueFull | 53600 | qos_queue_full | ResourceLimit | QoS queue full — per-level cap on concurrent/queued requests exceeded. |
FeatureNotSupported | 0A000 | feature_not_supported | InvalidInput | Requested feature is not supported by this version of AngaraBase. |
UndefinedFunction | 42883 | undefined_function | InvalidInput | Operator or function not found for the given argument types. |
InvalidColumnReference | 42P10 | invalid_column_reference | InvalidInput | Invalid column reference (e.g., ORDER BY ordinal out of range). |
SyntaxError | 42601 | syntax_error | InvalidInput | SQL syntax error in the submitted query. |
NoActiveSqlTransaction | 25P01 | no_active_sql_transaction | TransactionControl | Command requires an active transaction but none is in progress. |
ActiveSqlTransaction | 25001 | active_sql_transaction | TransactionControl | Command cannot be executed within an active transaction block. |
ReadOnlySqlTransaction | 25006 | read_only_sql_transaction | TransactionControl | Write operation attempted in a read-only transaction. |
IdleInTransactionTimeout | 57P01 | idle_in_transaction_session_timeout | ResourceLimit | Session exceeded idle_in_transaction_session_timeout. |
Troubleshooting
Handling TransactionAborted (40001)
When AngaraBase returns SQLSTATE 40001 (serialization_failure), the client should retry the transaction.
This is standard MVCC behaviour — a concurrent writer committed first.
-- Client retry pattern:
BEGIN;
-- ... operations ...
-- If you get 40001, retry from BEGIN
COMMIT;
Handling ResourceExhausted (53000)
Hard resource exhaustion (memory / connection limits). Check
angarabase_server_connections_active; if near max_connections, either:
- Increase
max_connections(requires restart — it is an instance-scope setting) - Use connection pooling (PgBouncer)
Handling QosQueueFull (53600)
The per-ServiceLevel QoS admission cap was exceeded. Unlike 53000, this code is
transient and safe to retry: back off with jitter and let lower-priority work
drain. See the Resource Contracts reference for the full fail-closed boundary table.
Configuration Reference
AngaraBase configuration knobs are managed through the SETTINGS_REGISTRY in engine-utils.
Knobs can be set via SET <name> = <value> (session scope) or in the server config file (global scope).
How to Apply Settings
-- Session scope (immediate, affects current connection only):
SET max_connections = 200;
-- View current value:
SHOW max_connections;
For global (persistent) settings, edit the server configuration file (angarabase.toml):
# angarabase.toml — server configuration file
max_connections = 200
storage.data_directory = "/var/lib/angarabase/data"
transaction_log.durability = "strict"
tls.enabled = true
tls.cert_path = "/etc/angarabase/server.crt"
tls.key_path = "/etc/angarabase/server.key"
Dynamic vs. Static settings:
Dynamic: true— takes effect immediately viaSETwithout server restartDynamic: false— requires server restart to take effect (instance-scope settings)
Typical Production Configuration
# Minimal production-ready angarabase.toml
max_connections = 200
server.addr = "0.0.0.0:5432"
storage.data_directory = "/var/lib/angarabase/data"
storage.transaction_log_directory = "/var/lib/angarabase/wal"
transaction_log.durability = "strict" # fsync on every commit
transaction_log.wal_compression = "lz4" # reduce WAL disk usage
tls.enabled = true
tls.require_on_remote_bind = true
auth.mode = "scram_sha256"
security.dev_mode = false
Configuration Knobs
Dynamic: false means the setting requires a server restart to take effect. Has Validator: yes means invalid values are rejected at
SETtime with SQLSTATE22023.
| Name | Default | Scope | Dynamic | Has Validator | Description |
|---|---|---|---|---|---|
max_connections | 100 | instance | false | yes | Maximum number of concurrent client connections (0 = unlimited). |
server.addr | 127.0.0.1:5152 | instance | false | no | pgwire bind address in host:port format (e.g. 127.0.0.1:5152 or 0.0.0.0:5432) |
server.host | `` | instance | false | no | DEPRECATED: use server.addr instead. pgwire bind host |
server.port | `` | instance | false | no | DEPRECATED: use server.addr instead. pgwire bind port |
storage.data_directory | `` | instance | false | no | storage data dir (immutable) |
storage.transaction_log_directory | `` | instance | false | no | txlog dir (immutable) |
transaction_log.backend | file | instance | false | no | transaction log backend (noop/file/file_bin) |
transaction_log.durability | strict | instance | false | no | transaction log durability (strict/relaxed/group_commit) |
transaction_log.fsync | true | instance | false | yes | transaction log fsync (strict mode; dev override) |
transaction_log.group_commit_v2 | false | instance | false | yes | group_commit waiter batching toggle |
transaction_log.wal_compression | off | instance | false | no | WAL compression mode: off|lz4|zstd |
transaction_log.wal_compression_min_bytes | 256 | instance | false | yes | minimum payload bytes for compression attempt |
transaction_log.wal_archive_enable | false | instance | false | yes | append durable WAL bytes to archive stream |
transaction_log.wal_archive_dir | /tmp/angarabase-dev/wal_archive | instance | false | no | WAL archive directory path |
security.dev_mode | false | instance | false | yes | development mode preset |
security.allow_insecure | false | instance | false | yes | allow insecure combinations (explicit override) |
security.tde_enabled | false | instance | false | yes | transparent data encryption toggle |
security.tde_master_key_id | `` | instance | false | no | non-secret TDE master key identifier |
security.tde_last_rotation_unix | 0 | instance | false | yes | last TDE key rotation time (unix seconds) |
tls.enabled | false | instance | false | yes | enable pgwire TLS |
tls.cert_path | `` | instance | false | no | TLS cert path (PEM) |
tls.key_path | `` | instance | false | no | TLS key path (PEM) |
tls.require_on_remote_bind | false | instance | true | yes | refuse remote bind without TLS |
tls.gost_enabled | false | instance | false | yes | enable GOST crypto profiles (opt-in, fail-closed) |
tls.gost_cipher_suites | `` | instance | false | no | GOST cipher suites preference (TLS 1.2 + GOST ciphers) |
auth.mode | trust | instance | false | no | pgwire auth mode |
rbac.admin_users | `` | instance | true | no | seed list of RBAC admins |
audit.log_path | `` | instance | true | no | audit JSONL sink path |
audit.dml_mode | off | instance | true | no | audit DML policy mode: off|allowlist|denylist |
audit.dml_allowlist | `` | instance | true | no | audit DML allowlist (comma-separated table refs) |
audit.dml_denylist | `` | instance | true | no | audit DML denylist (comma-separated table refs) |
audit.export_json_enabled | false | instance | true | yes | enable JSON audit export worker |
audit.export_syslog_enabled | false | instance | true | yes | enable Syslog audit export worker |
audit.export_rate_limit_rps | 10 | instance | true | yes | audit export max events per second |
ops.allow_sql_shutdown | false | instance | true | yes | enable SQL shutdown trigger |
ops.shutdown_timeout_ms | 1000 | instance | true | yes | graceful shutdown timeout (ms) |
ops.metrics_addr | `` | instance | false | no | metrics bind addr |
ops.admin_addr | `` | instance | false | no | admin API bind addr |
lock_timeout | 0 | session | true | yes | session lock timeout (ms); 0=off |
statement_timeout | 0 | session | true | yes | statement execution timeout (ms); 0=off |
angara.consumer_id | `` | session | true | no | optional logical consumer identifier for the session |
sql.execution_mode | auto | instance | true | no | SQL execution mode: ir_auto|ir_only|ir_strict|force_vector|force_row |
sql.parallel.dop_cap_global | 4 | instance | true | yes | global cap for parallel workers available to SQL runtime |
sql.parallel.dop_cap_query | 2 | instance | true | yes | per-query cap for SQL parallel workers |
aqp_enabled | true | instance | true | yes | adaptive query processing global enable flag |
aqp_mode | conservative | instance | true | no | adaptive mode: conservative|aggressive |
aqp_min_query_time_ms | 100 | instance | true | yes | minimum query latency for learning |
aqp_learning_rate | 0.1 | instance | true | no | AQP EMA learning rate |
aqp_max_correction | 100.0 | instance | true | no | max correction multiplier |
aqp_memory_feedback_limit_mb | 1024 | instance | true | yes | global memory feedback cap in MB |
aqp_variance_threshold | 10.0 | instance | true | no | variance threshold to disable unstable corrections |
aqp_correction_cache_mb | 64 | instance | true | yes | in-memory correction cache budget in MB |
aqp_store_capacity_mb | 1024 | instance | true | yes | AQP advisory store capacity budget in MB |
learned_optimizer_enabled | false | instance | true | yes | learned optimizer master switch |
learned_optimizer_mode | active | instance | true | no | learned optimizer mode: active|shadow |
learned_optimizer_timeout_us | 50 | instance | true | yes | learned predict timeout per operator in microseconds |
learned_optimizer_memory_limit_mb | 64 | instance | true | yes | learned model in-memory budget in MB |
learned_optimizer_confidence_threshold | 0.5 | instance | true | no | global confidence floor for learned predictions |
learned_optimizer_max_nodes_per_query | 20 | instance | true | yes | maximum learned inference calls per query |
learned_optimizer_regression_window | 1000 | instance | true | yes | rolling window size for regression detection |
txn.max_write_set_pages | 65536 | instance | false | yes | max pages modified by one txn |
txn.max_write_set_bytes | 536870912 | instance | false | yes | max bytes modified by one txn |
buffer_pool.uncommitted_pages_ratio_hard | 0.5 | instance | false | no | hard limit for buffer-pool fraction of frames carrying uncommitted page-image deltas |
buffer_pool.backpressure.mode | block | instance | false | no | backpressure mode: block|fail_fast |
buffer_pool.backpressure.timeout_ms | 5000 | instance | false | yes | max wait time in block mode |
wal.vlf_enable | false | instance | true | yes | enable Variable Length Files for WAL |
wal.max_size_mb | 1024 | instance | true | yes | maximum WAL file size in MB |
wal.vlf_size_mb | 64 | instance | true | yes | VLF segment size in MB |
wal.init_vlfs | 4 | instance | true | yes | initial number of VLF segments |
execution.mode | auto | instance | true | no | SQL execution mode (auto/force_vector/force_row) |
execution.vector_batch_size | 4096 | instance | true | yes | vector execution batch size |
execution.query_memory_limit_mb | 256 | instance | true | yes | per-query memory limit in MB |
aqp.enabled | true | instance | true | yes | enable Adaptive Query Processing |
aqp.mode | conservative | instance | true | no | AQP mode (conservative/aggressive) |
aqp.min_query_time_ms | 100 | instance | true | yes | minimum query time for AQP feedback |
aqp.learning_rate | 0.1 | instance | true | no | AQP EMA learning rate |
aqp.max_correction | 100.0 | instance | true | no | maximum AQP correction multiplier |
aqp.variance_threshold | 10.0 | instance | true | no | variance threshold for unstable corrections |
aqp.correction_cache_mb | 64 | instance | true | yes | AQP correction cache size in MB |
aqp.store_capacity_mb | 1024 | instance | true | yes | AQP store capacity in MB |
diagnostics.log_min_duration_ms | -1 | instance | true | yes | slow query log threshold in ms (-1=disabled) |
diagnostics.log_query_text | false | instance | true | yes | include query text in slow log |
diagnostics.stat_statements_max | 1024 | instance | true | yes | max stat_statements entries (0=disabled) |
checkpoint.dirty_track_enabled | true | instance | false | yes | Enable dirty-page bitmap for O(dirty) checkpoint scans instead of O(total) full scan. When true (default) the checkpoint worker uses BufferPool.checkpoint_dirty to skip checkpoints entirely when no pages have been written since the last flush. |
logging.log_level | info | instance | true | yes | structured logging level (error/warn/info/debug/trace) |
Deprecated Settings
Settings with deprecated_since set will log a warning when used. Migrate away before upgrading.
Validation
Settings with validators reject invalid values with SQLSTATE 22023 (invalid_parameter_value):
SET max_connections = 'abc';
-- ERROR: invalid value for parameter "max_connections": "abc" (SQLSTATE 22023)
Metrics Reference
AngaraBase exports Prometheus metrics on the /metrics endpoint (default port 9898, set via [ops] metrics_addr).
All metric names are prefixed with angarabase_.
Replaces:
docs/registries/metrics_surface_inventory_v0.txt(now deprecated).
Metric Types
| Type | Prometheus Kind | Description |
|---|---|---|
Gauge | gauge | Point-in-time value that can go up or down |
Counter | counter | Monotonically increasing value (always use rate() or increase()) |
Histogram | histogram | Distribution of values with configurable buckets |
Key Metrics by Category
Buffer Pool
Key metrics for monitoring buffer pool efficiency:
angarabase_buffer_pool_hit_total— cache hits; high ratio (>95%) is healthyangarabase_buffer_pool_miss_total— cache misses; spikes indicate memory pressureangarabase_buffer_pool_backpressure_active— 1 if backpressure active (memory pressure)
# 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
angarabase_checkpoint_duration_ms— checkpoint latency; target P99 < 200msangarabase_checkpoint_dirty_pages— dirty pages pending checkpoint flush
# Alert: checkpoint latency exceeding 200ms threshold
angarabase_checkpoint_duration_ms > 200
# Alert: checkpoint running on large dirty page set (potential I/O spike)
angarabase_checkpoint_dirty_pages > 10000
WAL
angarabase_wal_bytes_written_total— WAL write throughput
# WAL write throughput (bytes/sec):
rate(angarabase_wal_bytes_written_total[5m])
Connections
angarabase_connections_active— active connections; alert if nearmax_connections
# Alert: connections above 90% of max_connections
# (replace 100 with your actual max_connections value)
angarabase_connections_active / 100 > 0.9
# Rate of new connection attempts:
rate(angarabase_connections_accepted_total[1m])
Columnar Storage GC (0.6.6.11)
angarabase_columnar_manifest_gc_removed_total— ghost segment refs tombstoned by manifest GC; steady growth is normal, sharp spikes indicate manifest bloat.angarabase_columnar_compactor_dv_purged_total— columnar segments fully covered by delete vectors (DV) and purged by the compactor.angarabase_index_gc_dead_fraction— fraction of index entries currently marked dead (range 0–1). Values above 0.15 trigger a preemptive extra GC sweep.
# Rate of ghost segment refs being cleaned up (should be > 0 if compaction runs):
rate(angarabase_columnar_manifest_gc_removed_total[5m])
# Alert: index dead fraction rising above 20% (GC not keeping pace):
angarabase_index_gc_dead_fraction > 0.20
Full Metrics Table
| Metric Name | Type | Labels | Description |
|---|---|---|---|
angarabase_agg_stream_typed_key_total | Counter | none | Aggregation stream typed-key operations total. |
angarabase_aqp_feedback_applied_total | Counter | none | AQP correction feedback applied to optimizer total. |
angarabase_aqp_feedback_clamped_total | Counter | none | AQP correction feedback clamped by bounds total. |
angarabase_auto_analyze_triggered_total | Counter | none | Auto-analyze triggers total. |
angarabase_backpressure_active_sources | Gauge | none | Number of storage sources currently applying backpressure. |
angarabase_buffer_pool_backpressure_active | Gauge | none | Buffer pool backpressure currently active (1=yes, 0=no). |
angarabase_buffer_pool_backpressure_events_total | Counter | none | Buffer pool backpressure events total. |
angarabase_buffer_pool_decomp_spill_total | Counter | none | Buffer pool decompression spills to disk total. |
angarabase_buffer_pool_evict_failed_total | Counter | none | Buffer pool page eviction failures total. |
angarabase_buffer_pool_hit_ratio_milli | Gauge | none | Buffer pool hit ratio × 1000 (milli-fraction). |
angarabase_buffer_pool_hit_total | Counter | none | Buffer pool cache hits total. |
angarabase_buffer_pool_miss_total | Counter | none | Buffer pool cache misses total. |
angarabase_buffer_pool_over_capacity_pages | Gauge | none | Pages loaded above configured buffer pool capacity. |
angarabase_buffer_pool_uncommitted_dirty_pages | Gauge | none | Buffer pool frames carrying uncommitted page-image deltas. |
angarabase_buffer_pool_waiter_wait_seconds | Histogram | none | Time buffer pool waiters spend blocked waiting for a free frame. |
angarabase_buffer_pool_warmup_aborted_at_cap_total | Counter | none | Buffer pool warmup attempts aborted due to capacity limit total. |
angarabase_buffer_pool_warmup_completed_pages | Gauge | none | Pages loaded during last completed buffer pool warmup. |
angarabase_buffer_pool_warmup_evictions_during_warmup_total | Counter | none | Evictions that occurred during buffer pool warmup total. |
angarabase_buffer_pool_warmup_pages_total | Counter | none | Pages loaded by buffer pool warmup total. |
angarabase_buffer_ring_active_slots | Gauge | none | Active buffer ring slots. |
angarabase_buffer_ring_created_total | Counter | none | Buffer ring slots created total. |
angarabase_buffer_ring_dropped_total | Counter | none | Buffer ring slots dropped total. |
angarabase_buffer_ring_evictions_total | Counter | none | Buffer ring evictions total. |
angarabase_catalog_snapshot_segments_total | Gauge | none | Catalog snapshot segments currently held. |
angarabase_chain_read_legacy_fallback_total | Counter | none | Version-chain reads falling back to legacy path total. |
angarabase_chain_read_total | Counter | none | Version-chain reads total. |
angarabase_checkpoint_aborted_total | Counter | none | Checkpoints aborted total. |
angarabase_checkpoint_dirty_pages | Gauge | none | Dirty pages pending checkpoint flush. |
angarabase_checkpoint_dirty_pages_leq_target | Gauge | none | Dirty pages at or below checkpoint target (1=yes, 0=no). |
angarabase_checkpoint_errors_total | Counter | none | Checkpoint errors total. |
angarabase_checkpoint_index_flush_errors_total | Counter | none | Index flush errors during checkpoint total. |
angarabase_checkpoint_target_lsn_current | Gauge | none | Current checkpoint target LSN. |
angarabase_checkpoint_scan_pages_total | Counter | none | Total pages inspected during checkpoint (dirty bitmap: O(dirty pages); full scan: O(total pages)). |
angarabase_checkpoint_total | Counter | none | Checkpoints completed total. |
angarabase_column_cache_evictions_total | Counter | none | Columnar column cache evictions total. |
angarabase_column_cache_oom_rejected_total | Counter | none | Column cache allocations rejected due to OOM total. |
angarabase_columnar_compaction_bytes_read_total | Counter | none | Bytes read during columnar compaction total. |
angarabase_columnar_compaction_bytes_written_total | Counter | none | Bytes written during columnar compaction total. |
angarabase_columnar_compaction_total | Counter | none | Columnar compaction runs total. |
angarabase_columnar_delete_vectors_applied_rows_total | Counter | none | Rows affected by columnar delete vectors total. |
angarabase_columnar_delete_vectors_attached_total | Counter | none | Columnar delete vectors attached total. |
angarabase_columnar_direct_io_fallback_total | Counter | none | Columnar reads falling back from direct I/O total. |
angarabase_columnar_dml_duration_ms | Histogram | none | Columnar DML operation duration in milliseconds. |
angarabase_columnar_manifest_init_failed_total | Counter | none | Columnar manifest initialisation failures total. |
angarabase_committed_version_exhausted_total | Counter | none | Committed version slot exhaustion events total. |
angarabase_compress_duration_us_total | Counter | none | Cumulative compression time in microseconds. |
angarabase_compress_ops_total | Counter | none | Compression operations total. |
angarabase_compression_downgrade_total | Counter | none | Compression algorithm downgrades (payload too small) total. |
angarabase_compression_ratio_ema_milli | Gauge | none | EMA compression ratio × 1000. |
angarabase_config_unknown_keys_total | Counter | none | Unknown configuration keys encountered at startup total. |
angarabase_deadlock_detected_total | Counter | none | Deadlocks detected by the lock manager total. |
angarabase_decompress_duration_us_total | Counter | none | Cumulative decompression time in microseconds. |
angarabase_decompress_ops_total | Counter | none | Decompression operations total. |
angarabase_deployment_probe_cgroup_v1 | Gauge | none | Deployment probe detected cgroup v1 (1=yes, 0=no). |
angarabase_deployment_probe_cgroup_v2 | Gauge | none | Deployment probe detected cgroup v2 (1=yes, 0=no). |
angarabase_deployment_probe_fallback_total | Counter | none | Deployment probe fallback events total. |
angarabase_deployment_probe_override_blocked_total | Counter | none | Deployment probe override blocked events total. |
angarabase_deployment_probe_runs_total | Counter | none | Deployment probe runs total. |
angarabase_deployment_profile_bare_metal_total | Counter | none | Deployments on bare-metal profile total. |
angarabase_deployment_profile_container_total | Counter | none | Deployments on container profile total. |
angarabase_engine_optimizer_catalog_row_count_fallback_total | Counter | none | Optimizer catalog row-count fallback events total. |
angarabase_engine_optimizer_index_scan_chosen_total | Counter | none | Optimizer chose index scan total. |
angarabase_engine_optimizer_small_table_seq_scan_total | Counter | none | Optimizer chose sequential scan for small table total. |
angarabase_engine_optimizer_stale_stats_fallback_total | Counter | none | Optimizer fell back due to stale statistics total. |
angarabase_expr_ir_arena_chunks_total | Counter | none | Expression IR arena chunks allocated total. |
angarabase_expr_ir_arena_released_bytes_total | Counter | none | Expression IR arena bytes released total. |
angarabase_expr_ir_arena_reserved_bytes_total | Counter | none | Expression IR arena bytes reserved total. |
angarabase_expr_ir_fallback_total | Counter | none | Expression IR evaluation fallbacks total. |
angarabase_fsync_timeout_total | Counter | none | fsync timeout events total. |
angarabase_gc_background_ticks_total | Counter | none | GC background tick cycles total. |
angarabase_gc_compact_calls_total | Counter | none | GC compaction calls total. |
angarabase_gc_compact_history_versions_removed_total | Counter | none | Old MVCC history versions removed by GC compaction total. |
angarabase_gc_compact_slice_duration_ms_bucket_1 | Counter | none | GC compact slice duration histogram bucket ≤1ms. |
angarabase_gc_compact_slice_duration_ms_bucket_10 | Counter | none | GC compact slice duration histogram bucket ≤10ms. |
angarabase_gc_compact_slice_duration_ms_bucket_100 | Counter | none | GC compact slice duration histogram bucket ≤100ms. |
angarabase_gc_compact_slice_duration_ms_bucket_5 | Counter | none | GC compact slice duration histogram bucket ≤5ms. |
angarabase_gc_compact_slice_duration_ms_bucket_50 | Counter | none | GC compact slice duration histogram bucket ≤50ms. |
angarabase_gc_compact_slice_duration_ms_bucket_500 | Counter | none | GC compact slice duration histogram bucket ≤500ms. |
angarabase_gc_compact_slice_duration_ms_bucket_inf | Counter | none | GC compact slice duration histogram bucket +Inf. |
angarabase_gc_compact_slice_duration_ms_count | Counter | none | GC compact slice duration histogram observation count. |
angarabase_gc_compact_slice_duration_ms_sum | Counter | none | GC compact slice duration histogram sum (ms). |
angarabase_gc_compact_slices_total | Counter | none | GC compaction slices processed total. |
angarabase_gc_compact_tables_removed_total | Counter | none | Tables fully removed by GC compaction total. |
angarabase_gc_compact_tables_scanned_total | Counter | none | Tables scanned by GC compaction total. |
angarabase_gc_compact_versions_removed_total | Counter | none | MVCC versions removed by GC compaction total. |
angarabase_gc_tuning_bloat_ratio_percent | Gauge | none | GC tuning: current bloat ratio estimate (percent). |
angarabase_gc_tuning_budget_tuples_per_cycle | Gauge | none | GC tuning: adaptive budget tuples per cycle. |
angarabase_gc_tuning_cycle_duration_ms_last | Gauge | none | Last GC tuning cycle duration in ms. |
angarabase_gc_tuning_decision_total_decrease | Counter | none | GC tuning decisions to decrease budget total. |
angarabase_gc_tuning_decision_total_hold | Counter | none | GC tuning decisions to hold budget total. |
angarabase_gc_tuning_decision_total_increase | Counter | none | GC tuning decisions to increase budget total. |
angarabase_gc_tuning_min_active_epoch_lag | Gauge | none | Minimum active epoch lag seen by GC tuner. |
angarabase_gc_tuning_sleep_ms | Gauge | none | GC tuner current sleep interval in ms. |
angarabase_gc_watermark_snapshot | Gauge | none | GC safe watermark snapshot epoch. |
angarabase_gc_pages_compacted_total | Counter | none | Heap pages compacted by GcWorker (dead-tuple reclaim) total. |
angarabase_gc_dead_tuples_reclaimed_total | Counter | none | Dead tuple slots reclaimed by GcWorker total. |
angarabase_group_commit_batches_total | Counter | none | WAL group-commit batches flushed total. |
angarabase_hash_join_build_rows_total | Counter | none | Hash join build-side rows processed total. |
angarabase_hash_join_probe_rows_total | Counter | none | Hash join probe-side rows processed total. |
angarabase_hash_join_spilled_to_nested_loop_total | Counter | none | Hash joins that spilled and fell back to nested loop total. |
angarabase_heap_deletes_total | Counter | none | Heap row deletions total. |
angarabase_heap_dml_errors_total | Counter | none | Heap DML errors total. |
angarabase_heap_inserts_total | Counter | none | Heap row insertions total. |
angarabase_heap_pages_flushed_on_shutdown | Counter | none | Heap pages flushed during graceful shutdown. |
angarabase_heap_point_fetch_fallback_reason_not_found_total | Counter | none | Heap point-fetch fallbacks: row not found total. |
angarabase_heap_point_fetch_fallback_reason_stale_tid_index_total | Counter | none | Heap point-fetch fallbacks: stale TID index total. |
angarabase_heap_point_fetch_fallback_total | Counter | none | Heap point-fetch fallbacks total. |
angarabase_heap_point_fetch_total | Counter | none | Heap point-fetch attempts total. |
angarabase_heap_tid_index_ready | Gauge | none | Heap TID index readiness (1=ready, 0=not ready). |
angarabase_heap_updates_total | Counter | none | Heap row updates total. |
angarabase_htap_staleness_ms | Gauge | none | HTAP read-replica staleness in milliseconds. |
angarabase_idle_txn_killed_total | Counter | none | Idle transactions killed by the idle-timeout janitor total. |
angarabase_index_build_aborts_total | Counter | none | Index build aborts total. |
angarabase_index_builds_total | Counter | none | Index builds started total. |
angarabase_index_deletes_total | Counter | none | Index key deletions total. |
angarabase_index_drops_total | Counter | none | Index drop operations total. |
angarabase_index_inserts_total | Counter | none | Index key insertions total. |
angarabase_index_lookups_total | Counter | none | Index lookup operations total. |
angarabase_index_migration_completed_total | Counter | none | Index migrations completed total. |
angarabase_index_migration_failed_total | Counter | none | Index migration failures total. |
angarabase_index_not_found_total | Counter | none | Index lookup: key not found total. |
angarabase_index_only_scan_heap_fetches_total | Counter | none | Heap fetches during index-only scans total. |
angarabase_index_only_scan_hits_total | Counter | none | Index-only scan hits (no heap fetch required) total. |
angarabase_index_pages_total | Gauge | index_name | Total pages in an index. |
angarabase_index_pkey_no_table_id_total | Gauge | none | Primary-key index entries with no resolved table ID. |
angarabase_index_range_scans_total | Counter | none | Index range scan operations total. |
angarabase_index_reject_total | Counter | none | Index operation rejections total. |
angarabase_index_restore_empty_labeled_total | Counter | index, db | Empty index restores (with index+db label) total. |
angarabase_index_restore_empty_total | Counter | none | Empty index restores total. |
angarabase_index_restore_failed_total | Counter | index, db | Index restore failures total. |
angarabase_index_routing_legacy_total | Counter | db | Index routing via legacy path total. |
angarabase_index_scan_rows_fetched_total | Counter | none | Rows fetched via index scan total. |
angarabase_index_stale_tuple_fallbacks_total | Counter | none | Index scan stale-tuple fallbacks total. |
angarabase_io_advisor_current_batch_size | Gauge | none | IO advisor current adaptive batch size. |
angarabase_io_backend_active | Gauge | backend | IO backend active (1=active) per backend. |
angarabase_io_backend_active_component | Gauge | component, backend | IO backend active per component and backend. |
angarabase_io_complete_total | Counter | op | IO completions total per operation type. |
angarabase_io_error_total | Counter | op | IO errors total per operation type. |
angarabase_io_submit_total | Counter | op | IO submissions total per operation type. |
angarabase_io_uring_active_instances | Gauge | none | Active io_uring ring instances. |
angarabase_io_uring_backpressure_total | Counter | none | io_uring backpressure events total. |
angarabase_io_uring_cqe_completed_total | Counter | none | io_uring CQEs completed total. |
angarabase_io_uring_direct_submit_total | Counter | none | io_uring direct (non-SQPOLL) submissions total. |
angarabase_io_uring_fallback_total | Counter | none | io_uring operations falling back to pread/pwrite total. |
angarabase_io_uring_inflight_high | Gauge | none | io_uring high-watermark inflight operations. |
angarabase_io_uring_inflight_low | Gauge | none | io_uring low-watermark inflight operations. |
angarabase_io_uring_parallel_inflight_high | Gauge | none | io_uring parallel inflight high-watermark. |
angarabase_io_uring_parallel_inflight_low | Gauge | none | io_uring parallel inflight low-watermark. |
angarabase_io_uring_read_fixed_total | Counter | none | io_uring fixed-buffer reads total. |
angarabase_io_uring_registered_buffers_count | Gauge | none | io_uring registered buffer count. |
angarabase_io_uring_sqe_submitted_total | Counter | none | io_uring SQEs submitted total. |
angarabase_io_uring_sqpoll_enabled | Gauge | none | io_uring SQPOLL mode enabled (1=yes, 0=no). |
angarabase_io_uring_task_panic_total | Counter | none | io_uring task panics total. |
angarabase_io_uring_wal_write_error_total | Counter | none | io_uring WAL write errors total. |
angarabase_io_uring_write_fixed_total | Counter | none | io_uring fixed-buffer writes total. |
angarabase_ir_ddl_executed_total | Counter | none | IR-path DDL statements executed total. |
angarabase_ir_dml_executed_total | Counter | none | IR-path DML statements executed total. |
angarabase_ir_legacy_path_violation_total | Counter | none | IR legacy path violations detected total. |
angarabase_ir_plan_depth_reject_total | Counter | none | IR plans rejected for excessive depth total. |
angarabase_ir_plan_executed_total | Counter | none | IR plans executed total. |
angarabase_l0_blob_bytes_written_total | Counter | none | L0 blob bytes written total. |
angarabase_l0_blobs_active | Gauge | none | Active L0 blobs. |
angarabase_legacy_fallback_triggered_total | Counter | none | Legacy SQL execution fallbacks triggered total. |
angarabase_lock_acquire_total | Counter | none | Lock acquisitions total. |
angarabase_lock_timeout_total | Counter | none | Lock acquisition timeouts total. |
angarabase_manifest_log_appends_total | Counter | none | Manifest log appends total. |
angarabase_manifest_log_checkpoints_total | Counter | none | Manifest log checkpoints total. |
angarabase_manifest_log_replay_records_total | Counter | none | Manifest log records replayed total. |
angarabase_merge_join_executions_total | Counter | none | Merge join executions total. |
angarabase_mvcc_history_versions_total | Gauge | none | Total MVCC history versions held. |
angarabase_notify_delivered_total | Counter | none | LISTEN/NOTIFY notifications delivered total. |
angarabase_notify_dropped_total | Counter | none | LISTEN/NOTIFY notifications dropped total. |
angarabase_notify_listeners_active | Gauge | none | Active LISTEN subscribers. |
angarabase_optimizer_decorrelation_fallback_non_equi_predicate_total | Counter | none | Optimizer decorrelation fallback: non-equi predicate total. |
angarabase_optimizer_decorrelation_fallback_null_semantics_risk_total | Counter | none | Optimizer decorrelation fallback: null semantics risk total. |
angarabase_optimizer_decorrelation_fallback_total | Counter | none | Optimizer decorrelation fallbacks total. |
angarabase_optimizer_decorrelation_fallback_unsafe_pattern_total | Counter | none | Optimizer decorrelation fallback: unsafe pattern total. |
angarabase_optimizer_dp_fallback_total | Counter | none | Optimizer dynamic-programming join-order fallbacks total. |
angarabase_optimizer_memo_entries | Gauge | none | Optimizer memo table entries (last query). |
angarabase_optimizer_multicolumn_pairs_capped_total | Counter | none | Optimizer multicolumn pair evaluation capped total. |
angarabase_optimizer_queries_total | Counter | none | Queries processed by the optimizer total. |
angarabase_optimizer_replan_total_aqp_feedback | Counter | none | Optimizer replans triggered by AQP feedback total. |
angarabase_optimizer_replan_total_forced_fallback | Counter | none | Optimizer forced-fallback replans total. |
angarabase_optimizer_replan_total_schema_changed | Counter | none | Optimizer replans due to schema change total. |
angarabase_optimizer_replan_total_stats_drift | Counter | none | Optimizer replans due to stats drift total. |
angarabase_optimizer_stale_stats_total | Counter | none | Optimizer stale statistics encounters total. |
angarabase_optimizer_timeout_total | Counter | none | Optimizer timeout events total. |
angarabase_orphan_blobs_reclaimed_total | Counter | none | Orphan blobs reclaimed by GC total. |
angarabase_overlay_rows_evicted_total | Counter | none | TX overlay rows evicted total. |
angarabase_parallel_agg_total | Counter | none | Parallel aggregation executions total. |
angarabase_parallel_budget_exceeded_total | Counter | none | Parallel worker budget exceeded events total. |
angarabase_parallel_join_admitted_total | Counter | none | Parallel join operations admitted total. |
angarabase_parallel_join_slots_active | Gauge | none | Active parallel join slots. |
angarabase_parallel_join_throttled_total | Counter | none | Parallel join operations throttled total. |
angarabase_parallel_morsels_stolen_total | Counter | none | Parallel morsels stolen by work-stealing total. |
angarabase_parallel_morsels_total | Counter | none | Parallel morsels created total. |
angarabase_parallel_scan_total | Counter | none | Parallel scan operations total. |
angarabase_parallel_worker_cancel_total | Counter | none | Parallel worker cancellations total. |
angarabase_parallel_worker_starvation_events_total | Counter | none | Parallel worker starvation events total. |
angarabase_parallel_workers_active | Gauge | none | Currently active parallel workers. |
angarabase_parallel_workers_denied_by_cap_total | Counter | none | Parallel worker requests denied by DOP cap total. |
angarabase_partition_pruned_branches_total | Counter | none | Partition branches pruned by predicate pushdown total. |
angarabase_partition_route_default_total | Counter | none | Partition routes to default partition total. |
angarabase_partition_route_no_match_total | Counter | none | Partition routes with no matching partition total. |
angarabase_partition_route_ok_total | Counter | none | Successful partition routes total. |
angarabase_pgwire_active_tasks | Gauge | none | Active pgwire tasks (queries in flight). |
angarabase_pgwire_pool_active_workers | Gauge | none | Active pgwire workers (async spawn_blocking tasks or legacy pool busy workers). |
angarabase_pgwire_pool_queue_depth | Gauge | none | pgwire pool pending connection queue depth. |
angarabase_pgwire_pool_rejected_total | Counter | none | pgwire connections rejected by pool limit total. |
angarabase_pgwire_simple_queries_total | Counter | none | pgwire simple-query protocol messages total. |
angarabase_pkey_backfill_fail_total | Counter | none | Primary-key backfill failures total. |
angarabase_pkey_backfill_in_progress | Gauge | none | Primary-key backfill operations in progress. |
angarabase_pkey_backfill_ok_total | Counter | none | Primary-key backfill completions total. |
angarabase_plan_cache_dml_hit_duration_us | Histogram | none | DML plan cache hit latency in microseconds. |
angarabase_plan_cache_dml_hits_total | Counter | none | DML plan cache hits total. |
angarabase_plan_cache_dml_misses_total | Counter | none | DML plan cache misses total. |
angarabase_plan_cache_dml_param_extract_error_total | Counter | none | DML plan cache parameter extraction errors total. |
angarabase_plan_cache_dml_schema_miss_total | Counter | none | DML plan cache schema mismatch misses total. |
angarabase_plan_cache_evictions_total | Counter | none | Plan cache evictions total. |
angarabase_plan_cache_hits_total | Counter | none | Plan cache hits total. |
angarabase_plan_cache_invalidations_total | Counter | none | Plan cache invalidations total. |
angarabase_plan_cache_misses_total | Counter | none | Plan cache misses total. |
angarabase_plan_cache_size | Gauge | none | Current plan cache entry count. |
angarabase_prefetch_hints_total | Counter | none | Prefetch hints issued total. |
angarabase_projection_pruning_cols_eliminated_total | Counter | none | Columns eliminated by projection pruning total. |
angarabase_qos_blocking_inflight | Gauge | none | QoS blocking inflight operations. |
angarabase_qos_priority_inherit_total | Counter | from, to | QoS priority inheritance events total. |
angarabase_qos_queued_background_total | Counter | none | QoS background-priority requests queued total. |
angarabase_qos_queued_critical_total | Counter | none | QoS critical-priority requests queued total. |
angarabase_qos_queued_interactive_total | Counter | none | QoS interactive-priority requests queued total. |
angarabase_qos_rejected_background_total | Counter | none | QoS background-priority requests rejected total. |
angarabase_qos_rejected_critical_total | Counter | none | QoS critical-priority requests rejected total. |
angarabase_qos_rejected_interactive_total | Counter | none | QoS interactive-priority requests rejected total. |
angarabase_query_exec_duration_ms | Histogram | none | Query execution duration in milliseconds. |
angarabase_query_exec_total | Counter | outcome, class | Query executions total by outcome and class. |
angarabase_query_feedback_events_total | Counter | reason | Query feedback events emitted total. |
angarabase_query_store_entries_total | Gauge | none | Query store current entry count. |
angarabase_query_store_evictions_total | Counter | none | Query store evictions total. |
angarabase_query_store_intervals_flushed_total | Counter | none | Query store intervals flushed to WAL total. |
angarabase_query_store_mode | Gauge | none | Query store current mode (encoded integer). |
angarabase_query_store_plans_total | Gauge | none | Query store current plan count. |
angarabase_query_store_regressions_detected_total | Counter | none | Query regressions detected by the query store total. |
angarabase_query_store_rotations_total | Counter | none | Query store interval rotations total. |
angarabase_query_store_wal_errors_total | Counter | none | Query store WAL write errors total. |
angarabase_recovery_analysis_ms | Gauge | none | Recovery analysis phase duration in ms. |
angarabase_recovery_clr_records | Counter | none | Recovery CLR (compensation log) records replayed total. |
angarabase_recovery_dirty_pages | Gauge | none | Dirty pages remaining after recovery redo. |
angarabase_recovery_redo_records | Counter | none | Recovery redo records applied total. |
angarabase_recovery_replay_pages_applied_total | Counter | none | Recovery page replay: pages applied total. |
angarabase_recovery_replay_pages_runs_total | Counter | none | Recovery page replay runs total. |
angarabase_recovery_replay_pages_skipped_total | Counter | none | Recovery page replay: pages skipped total. |
angarabase_recovery_undo_txns | Counter | none | Transactions rolled back during recovery total. |
angarabase_scan_stream_batches_total | Counter | none | Scan stream batches produced total. |
angarabase_scan_stream_fallback_total | Counter | none | Scan stream fallbacks to row-by-row total. |
angarabase_scan_stream_materialize_total | Counter | reason | Scan stream materialise operations total by reason. |
angarabase_sequence_currval_total | Counter | none | CURRVAL calls total. |
angarabase_sequence_nextval_total | Counter | none | NEXTVAL calls total. |
angarabase_sequence_overflow_total | Counter | none | Sequence overflow events total. |
angarabase_sequence_owned_create_failed_total | Counter | none | Owned sequence create failures total. |
angarabase_sequence_owned_lazy_migration_total | Counter | none | Owned sequence lazy migrations total. |
angarabase_sequence_owned_nextval_total | Counter | none | Owned sequence NEXTVAL calls total. |
angarabase_sequence_setval_total | Counter | none | SETVAL calls total. |
angarabase_server_connections_accepted_total | Counter | none | Server connections accepted total. |
angarabase_server_connections_active | Gauge | none | Currently active server connections. |
angarabase_session_claims_set_total | Counter | none | Session JWT claim SET operations total. |
angarabase_shutdown_dirty_pages_remaining | Gauge | none | Dirty pages remaining at shutdown start. |
angarabase_slow_query_total | Counter | none | Slow queries exceeding log_min_duration_ms total. |
angarabase_spawn_blocking_active | Gauge | none | Active spawn_blocking tasks. |
angarabase_spawn_blocking_max | Gauge | none | Maximum observed spawn_blocking concurrency. |
angarabase_spill_bytes_in_use | Gauge | none | Spill storage bytes currently in use. |
angarabase_spill_bytes_total | Counter | none | Total bytes spilled to disk. |
angarabase_spill_direct_io_supported | Gauge | none | Spill direct I/O supported on this filesystem (1=yes). |
angarabase_spill_files_total | Counter | none | Spill files created total. |
angarabase_spill_hash_join_bloom_filtered_probe_rows_total | Counter | none | Hash join bloom-filtered probe rows total. |
angarabase_spill_hash_join_recursion_depth_overflow_total | Counter | none | Hash join recursion depth overflow events total. |
angarabase_spill_hash_join_recursive_partitions_total | Counter | none | Recursive spill partitions created total. |
angarabase_spill_hash_join_skew_fallback_total | Counter | none | Hash join skew fallbacks total. |
angarabase_spill_otmpfile_with_direct_supported | Gauge | none | O_TMPFILE with direct I/O supported (1=yes). |
angarabase_spill_soft_quota_reached_total | Counter | none | Spill soft quota reached events total. |
angarabase_sql_correlated_budget_reject_total | Counter | none | Correlated subquery budget rejections total. |
angarabase_sql_cross_join_budget_reject_total | Counter | none | Cross join budget rejections total. |
angarabase_sql_default_nextval_reject_total | Counter | none | DEFAULT NEXTVAL rejections total. |
angarabase_sql_full_join_fallback_total | Counter | none | FULL JOIN fallbacks total. |
angarabase_sql_identity_override_reject_total | Counter | none | IDENTITY ALWAYS override rejections total. |
angarabase_sql_join_rows_produced_cross_total | Counter | none | Rows produced by cross joins total. |
angarabase_sql_join_rows_produced_full_total | Counter | none | Rows produced by full outer joins total. |
angarabase_sql_join_rows_produced_inner_total | Counter | none | Rows produced by inner joins total. |
angarabase_sql_join_rows_produced_lateral_total | Counter | none | Rows produced by lateral joins total. |
angarabase_sql_join_rows_produced_left_total | Counter | none | Rows produced by left outer joins total. |
angarabase_sql_join_rows_produced_right_total | Counter | none | Rows produced by right outer joins total. |
angarabase_sql_routing_total | Counter | decision | SQL routing decisions total by decision type. |
angarabase_sql_scalar_subquery_cardinality_violations_total | Counter | none | Scalar subquery cardinality violations total. |
angarabase_sql_sequence_allocations_identity_always_total | Counter | none | Sequence allocations for IDENTITY ALWAYS columns total. |
angarabase_sql_sequence_allocations_identity_by_default_total | Counter | none | Sequence allocations for IDENTITY BY DEFAULT columns total. |
angarabase_sql_sequence_allocations_serial_total | Counter | none | Sequence allocations for SERIAL columns total. |
angarabase_sql_upsert_conflict_total | Counter | none | UPSERT conflict events total. |
angarabase_sql_upsert_do_nothing_total | Counter | none | UPSERT ON CONFLICT DO NOTHING events total. |
angarabase_sql_upsert_do_update_total | Counter | none | UPSERT ON CONFLICT DO UPDATE events total. |
angarabase_stat_statements_entries_current | Gauge | none | Current stat_statements entry count. |
angarabase_stat_statements_evicted_total | Counter | none | stat_statements LRU evictions total (high rate → literal normalization gap). |
angarabase_storage_backpressure_commit_rejected_total | Counter | none | Commits rejected by storage backpressure total. |
angarabase_storage_backpressure_events_total | Counter | none | Storage backpressure events total. |
angarabase_storage_cached_pages_total | Gauge | none | Pages currently cached in the storage layer. |
angarabase_storage_dirty_pages_total | Gauge | none | Total dirty pages in the storage layer. |
angarabase_storage_flush_append_total | Counter | none | Storage flush append operations total. |
angarabase_storage_flush_bytes_total | Counter | none | Storage flush bytes written total. |
angarabase_storage_flush_duration_seconds | Histogram | none | Storage flush operation duration in seconds. |
angarabase_storage_flush_eviction_duration_ms_last | Gauge | none | Last storage flush eviction duration in ms. |
angarabase_storage_flush_full_total | Counter | none | Storage full flushes total. |
angarabase_storage_flush_ok_total | Counter | none | Successful storage flush operations total. |
angarabase_storage_flush_skipped_page_lsn_ahead_total | Counter | none | Storage flush skips: page LSN ahead of flush LSN total. |
angarabase_storage_flush_skipped_pinned_total | Counter | none | Storage flush skips: page pinned total. |
angarabase_storage_flush_skipped_uncommitted_total | Counter | none | Storage flush skips: uncommitted page total. |
angarabase_storage_io_read_duration_ms | Histogram | none | Storage I/O read duration in milliseconds. |
angarabase_storage_io_write_duration_ms | Histogram | none | Storage I/O write duration in milliseconds. |
angarabase_storage_per_table_engine_fallback_total | Counter | none | Per-table engine fallback events total. |
angarabase_storage_per_table_engines_count | Gauge | none | Number of per-table storage engine overrides. |
angarabase_storage_scan_errors_total | Gauge | none | Storage scan errors total. |
angarabase_storage_sync_data_total | Counter | none | Storage data sync operations total. |
angarabase_stream_entries_total | Counter | none | Stream (CDC) entries published total. |
angarabase_stream_subscriptions_active | Gauge | none | Active stream subscriptions. |
angarabase_syscatalog_db_lazy_load_duration_ms_last | Gauge | none | Last system-catalog lazy-load duration in ms. |
angarabase_syscatalog_db_unavailable_total | Counter | none | System-catalog DB unavailable events total. |
angarabase_syscatalog_global_baseline_load_duration_ms_last | Gauge | none | Last system-catalog global baseline load duration in ms. |
angarabase_table_lock_contention_total | Counter | none | Table-level lock contention events total. |
angarabase_transaction_log_bytes_appended_total | Counter | none | WAL bytes appended total. |
angarabase_transaction_log_checkpoint_chain_broken_total | Counter | none | WAL checkpoint chain breaks total. |
angarabase_transaction_log_checkpoint_end_invalid_total | Counter | none | Invalid WAL checkpoint-end records total. |
angarabase_transaction_log_checkpoint_end_valid_total | Counter | none | Valid WAL checkpoint-end records total. |
angarabase_transaction_log_durable_lsn | Gauge | none | WAL durable (fsync-confirmed) LSN. |
angarabase_transaction_log_flush_lsn | Gauge | none | WAL flush (write-confirmed) LSN. |
angarabase_transaction_log_group_commit_pending_lsn | Gauge | none | WAL group-commit pending LSN. |
angarabase_transaction_log_group_commit_pumps_total | Counter | none | WAL group-commit pump iterations total. |
angarabase_transaction_log_lag_commit_minus_durable_lsn | Gauge | none | WAL lag: commit LSN minus durable LSN. |
angarabase_transaction_log_lag_flush_minus_durable_lsn | Gauge | none | WAL lag: flush LSN minus durable LSN. |
angarabase_transaction_log_lag_pending_minus_durable_lsn | Gauge | none | WAL lag: pending LSN minus durable LSN. |
angarabase_transaction_log_last_checkpoint_id | Gauge | none | WAL last checkpoint identifier. |
angarabase_transaction_log_last_checkpoint_target_lsn | Gauge | none | WAL last checkpoint target LSN. |
angarabase_transaction_log_last_commit_lsn | Gauge | none | WAL last commit LSN. |
angarabase_transaction_log_records_appended_total | Counter | none | WAL records appended total. |
angarabase_transaction_log_scan_stop_reason_total_bad_crc | Counter | none | WAL scan stopped: bad CRC total. |
angarabase_transaction_log_scan_stop_reason_total_bad_len | Counter | none | WAL scan stopped: bad record length total. |
angarabase_transaction_log_scan_stop_reason_total_bad_magic | Counter | none | WAL scan stopped: bad magic bytes total. |
angarabase_transaction_log_scan_stop_reason_total_bad_version | Counter | none | WAL scan stopped: bad version total. |
angarabase_transaction_log_scan_stop_reason_total_partial_record | Counter | none | WAL scan stopped: partial record total. |
angarabase_tx_overlay_dataset_bytes_total | Gauge | none | TX overlay dataset bytes in use. |
angarabase_tx_overlay_dataset_limit_exceeded_total | Counter | none | TX overlay dataset limit exceeded events total. |
angarabase_txn_active_count | Gauge | none | Currently active transactions. |
angarabase_txn_begin_total | Counter | none | Transactions begun total. |
angarabase_txn_commit_conflicts_total | Counter | none | Transaction commit conflicts (serialization failures) total. |
angarabase_txn_commit_epoch_current | Gauge | none | Current transaction commit epoch. |
angarabase_txn_commit_epoch_exhausted_total | Counter | none | Transaction commit epoch exhaustion events total. |
angarabase_txn_commit_total | Counter | none | Transactions committed total. |
angarabase_txn_id_exhausted_total | Counter | none | Transaction ID exhaustion events total. |
angarabase_txn_long_snapshot_hard_total | Counter | none | Long-running snapshot hard-limit violations total. |
angarabase_txn_long_snapshot_warn_total | Counter | none | Long-running snapshot warnings total. |
angarabase_txn_oldest_snapshot_age_seconds | Gauge | none | Age of the oldest active snapshot in seconds. |
angarabase_txn_release_savepoint_total | Counter | none | RELEASE SAVEPOINT calls total. |
angarabase_txn_rollback_to_savepoint_total | Counter | none | ROLLBACK TO SAVEPOINT calls total. |
angarabase_txn_rollback_total | Counter | none | Transactions rolled back total. |
angarabase_txn_savepoint_total | Counter | none | SAVEPOINT calls total. |
angarabase_txn_watermark_min_active | Gauge | none | Minimum active transaction watermark. |
angarabase_txn_watermark_safe_gc | Gauge | none | Safe GC watermark (all txns below this epoch are committed/aborted). |
angarabase_txn_watermark_safe_gc_lag_snapshots | Gauge | none | Number of snapshots lagging behind the safe GC watermark. |
angarabase_txn_write_set_limit_exceeded_total | Counter | none | Transactions rejected for exceeding write-set size limit total. |
angarabase_txn_write_set_pages_max | Gauge | none | Maximum write-set pages per transaction configuration. |
angarabase_undo_append_rejected_total | Counter | none | Undo log append rejections total. |
angarabase_undo_file_bytes | Gauge | none | Undo file size in bytes. |
angarabase_undo_gc_truncations_total | Counter | none | Undo GC truncations total. |
angarabase_undo_segments_total | Gauge | none | Total undo segments. |
angarabase_undo_store_bytes | Gauge | none | Undo store bytes in use. |
angarabase_uptime_seconds | Gauge | none | Server uptime in seconds. |
angarabase_vector_batches_produced_total | Counter | none | Vectorised execution batches produced total. |
angarabase_vector_columnar_native_total | Counter | none | Vector aggregate executions via native columnar batch pipeline. |
angarabase_columnar_batched_scan_batches_total | Counter | none | Columnar segment batches consumed by vector-native batched scans. |
angarabase_columnar_segments_pruned_total | Counter | none | Columnar segments pruned by zone-map predicate pushdown before blob I/O. |
angarabase_columnar_filtered_agg_late_mat_total | Counter | none | Filtered columnar aggregate scans using predicate-first late materialization. |
angarabase_vector_fallback_total | Counter | none | Vectorised execution fallbacks to row mode total. |
angarabase_vector_memory_budget_exceeded_total | Counter | none | Vector execution memory budget exceeded events total. |
angarabase_vector_rows_produced_total | Counter | none | Rows produced by vectorised execution total. |
angarabase_version_arena_capacity_exceeded_total | Counter | none | Version arena capacity exceeded events total. |
angarabase_version_chain_gc_removed_heads_total | Counter | none | Version chain GC: removed head entries total. |
angarabase_version_chain_rebuild_from_wal_total | Counter | none | Version chains rebuilt from WAL during recovery total. |
angarabase_version_head_map_size | Gauge | none | Version head map current entry count. |
angarabase_wal_decompressed_records_total | Counter | none | WAL records decompressed total. |
angarabase_wal_decompression_errors_total | Counter | none | WAL decompression errors total. |
angarabase_wal_group_commit_wait_total | Counter | none | WAL group-commit waiter events total. |
angarabase_wal_lsn_drift_resets_total | Counter | none | WAL LSN drift reset events total. |
angarabase_wal_record_iterator_lsn_order_violations_total | Counter | none | WAL record iterator LSN-order violations total. |
angarabase_wal_record_iterator_vlf_transitions_total | Counter | none | WAL record iterator VLF segment transitions total. |
angarabase_wal_sync_wait_total | Counter | none | WAL sync waits total. |
angarabase_write_hook_duration_ms_total | Counter | none | Write hook cumulative duration in ms. |
angarabase_write_hook_invocations_total | Counter | none | Write hook invocations total. |
angarabase_write_path_commits_ok_total | Counter | none | Write path successful commits total. |
angarabase_write_path_concurrent_waiters | Gauge | none | Current write path concurrent waiters. |
angarabase_write_path_lock_free_commits_total | Counter | none | Lock-free write path commits total. |
angarabase_write_path_phase_a_total | Counter | none | Write path phase-A (prepare) completions total. |
angarabase_write_path_phase_b_timeout_total | Counter | none | Write path phase-B timeouts total. |
angarabase_write_path_phase_b_total | Counter | none | Write path phase-B (commit) completions total. |
angarabase_write_path_serialized_commits_total | Counter | none | Serialized (non-lock-free) write path commits total. |
angarabase_write_write_conflicts_total | Counter | none | Write-write conflicts detected total. |
Database Object Types
Типы объектов, которыми управляет каталог AngaraBase. Зарезервированные (недоступные через SQL) типы в список не включены.
Поддерживаемые типы объектов
| Object Kind | DDL | sys_catalog | Status | Description |
|---|---|---|---|---|
| Table | CREATE TABLE | angara_sys.tables | Stable | Heap-based relation (primary storage). |
| Index | CREATE INDEX | angara_sys.indexes | Stable | Secondary B-tree index. |
| Sequence | CREATE SEQUENCE | angara_sys.sequences | Stable | Auto-increment generator. |
| Partition | CREATE TABLE ... PARTITION OF | angara_sys.partitions | Baseline | RANGE/LIST partition of a partitioned table. |
| Schema | CREATE SCHEMA | angara_sys.namespaces | Baseline | Namespace for objects. |
| Role | CREATE ROLE | angara_sys.roles | Baseline | Authentication principal (RBAC). |
| Constraint | ALTER TABLE ... ADD CONSTRAINT | angara_sys.constraints | Baseline | CHECK / UNIQUE / NOT NULL constraint. |
| ForeignKey | ALTER TABLE ... ADD FOREIGN KEY (NOT ENFORCED) | angara_sys.constraints | Baseline | Declarative referential constraint; NOT ENFORCED at runtime. |
Planned
Запланированы, но пока не доступны через SQL:
- View — Virtual relation based on a query.
- Function — User-defined function.
Типы данных SQL
Типы данных, поддерживаемые AngaraBase. Наличие OID в виртуальном pg_catalog (для интроспекции) не означает поддержку — в таблицу ниже включены только реально пригодные к использованию типы.
Поддерживаемые типы
| Тип | OID | pg_typeof | Статус | Описание |
|---|---|---|---|---|
bool | 16 | bool | Stable | Logical boolean (true/false). |
bytea | 17 | bytea | Stable | Variable-length binary string. |
int8 | 20 | int8 | Stable | 64-bit signed integer (bigint). |
int4 | 23 | int4 | Stable | 32-bit signed integer (integer). |
text | 25 | text | Stable | Variable-length character string. |
float8 | 701 | float8 | Stable | Double-precision floating-point. |
int2 | 21 | int2 | Baseline | 16-bit signed integer (smallint). |
float4 | 700 | float4 | Baseline | Single-precision floating-point (real). |
numeric | 1700 | numeric | Baseline | Exact numeric (Decimal-backed); explicit casts canonicalize. |
uuid | 2950 | uuid | Baseline | Universally unique identifier; explicit casts only. |
varchar | 1043 | varchar | Baseline | Variable-length character string (text-backed). |
bpchar | 1042 | bpchar | Baseline | Character string CHAR(n) (text-backed). |
mvarchar | 46001 | mvarchar | Baseline | 1C-compatible national VARCHAR: UTF-16LE semantics, case/trailing-space-insensitive collation, mvarchar(N). |
date | 1082 | date | Baseline | Calendar date (text-backed; minimal validation). |
timestamp | 1114 | timestamp | Baseline | Date and time, no time zone (text-backed). |
timestamptz | 1184 | timestamptz | Baseline | Date and time; parsed for casts / AS OF (tz not preserved). |
Planned
Зарегистрированы для интроспекции, но пока не пригодны к использованию (CAST к ним возвращает 0A000):
- time (
time) — Time of day (no time zone). - interval (
interval) — Time span. - json (
json) — Textual JSON data (json_* functions return text today). - jsonb (
jsonb) — Binary JSON data.
Контракты ресурсов (fail-closed)
AngaraBase ограничивает ресурсы по принципу restrictive-by-default: при достижении границы запрос отклоняется (или отменяется) детерминированным SQLSTATE, а не деградирует молча. Логика повторов на клиенте и правила алертинга должны строиться по этой таблице.
Границы ресурсов
| Граница | SQLSTATE | Условие | Параметр | Метрика | Wait-event |
|---|---|---|---|---|---|
| Connection limit Stable | 53000 | insufficient_resources | max_connections | angarabase_pgwire_pool_rejected_total | — |
| QoS admission (concurrent queries) Baseline | 53600 | qos_queue_full | — | angarabase_qos_rejected_critical_total | qos_queue |
| Per-transaction write set Baseline | 54023 | configuration_limit_exceeded | txn.max_write_set_bytes | — | — |
| Buffer-pool / commit backpressure Baseline | 53400 | insufficient_resources | buffer_pool.backpressure.mode | angarabase_buffer_pool_backpressure_events_total | buffer_pool_eviction |
| Query memory limit Baseline | 53400 | insufficient_resources | execution.query_memory_limit_mb | — | — |
| Statement timeout Stable | 57014 | query_canceled | statement_timeout | — | — |
| Lock wait timeout Stable | 55P03 | lock_not_available | lock_timeout | angarabase_lock_timeout_total | — |
| Idle-in-transaction timeout Stable | 57P01 | idle_in_transaction_session_timeout | — | angarabase_idle_txn_killed_total | — |
| Snapshot too old (UNDO budget) Baseline | 72000 | snapshot_too_old | — | — | — |
| Disk full Stable | 53100 | disk_full | — | — | — |
Поведение и реакция клиента
Connection limit — 53000
Reject the new connection once max_connections is reached; established sessions are unaffected.
Реакция клиента: Back off and retry; surface the signal to the connection pool / load balancer.
QoS admission (concurrent queries) — 53600
Reject when the per-ServiceLevel concurrency/queue cap is exceeded rather than queueing unboundedly.
Реакция клиента: Exponential back-off with jitter; lower-priority work is shed first. Distinct from 53000 so QoS rejects are safe to retry.
Per-transaction write set — 54023
Reject the DML once the per-transaction write set exceeds its byte/page budget; the transaction must roll back.
Реакция клиента: Roll back and retry with a smaller write batch, or raise txn.max_write_set_bytes / txn.max_write_set_pages.
Buffer-pool / commit backpressure — 53400
Park writers on buffer-pool eviction; once the uncommitted-pages / WAL-queue hard limit is hit, reject the commit with 53400 instead of unbounded buffering.
Реакция клиента: Reduce write batch size and retry after back-off; treat as a capacity signal for the operator. 53400 is transient (retryable).
Query memory limit — 53400
Spill operators (hash join, aggregation) to disk under memory pressure; reject with 53400 only when a spill partition cannot be admitted.
Реакция клиента: Reduce result/intermediate size (add predicates, lower batch size) or raise execution.query_memory_limit_mb.
Statement timeout — 57014
Cancel the running statement once statement_timeout elapses; partial results are discarded and the transaction must roll back.
Реакция клиента: Roll back; review the query plan before retrying the same statement.
Lock wait timeout — 55P03
Abort the lock acquisition once lock_timeout elapses (wait events: row_lock / page_lock / table_lock / transaction_lock).
Реакция клиента: Retry after back-off; reduce contention or shorten the transaction scope.
Idle-in-transaction timeout — 57P01
Terminate a session left idle inside an open transaction beyond the configured timeout.
Реакция клиента: Commit or roll back promptly; do not leave a transaction open while idle.
Snapshot too old (UNDO budget) — 72000
Force-close a reader whose snapshot needs UNDO records already purged under table-budget pressure.
Реакция клиента: Retry the whole transaction from the start; shorten long-running readers.
Disk full — 53100
Reject writes that would exceed available disk; fail-closed with no silent data loss.
Реакция клиента: Free space or extend storage; the write cannot proceed until capacity is available.
Глоссарий
Единый справочник терминов 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; до этого исполнение
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-пачки (один прогон):
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) -
Known issues (canonical):
angarabook/src/operations/known-issues.md
Unreleased (testing focus)
- 0.6.8.1 (in_review) — Bug-fix sprint (correctness + compatibility):
- highlights:
- Multi-statement Simple Query —
psql -c "stmt1; stmt2; …"(and any client) now executes every;-separated statement and returns each result, with PostgreSQL error semantics (first error aborts the rest). See Подключение клиентов §1.4. - G-17 fix — concurrent
UPDATE t SET v = v + 1 WHERE k = …on indexed/disk tables no longer silently loses increments (heap-primary MVCC + atomic read-modify-write). - G-16 fix — a graceful shutdown of a table with an index no longer loses committed rows on restart (the shutdown checkpoint now persists index pages before completing).
- Multi-statement Simple Query —
- highlights:
- 0.6.3.4 (in_review) — CBO P4.1 remediation:
- 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.
- highlights: optimizer planning timeout contract hardened (
- 5.17 (closed) — SQL Coverage Expansion:
- highlights: Window functions v0 (
ROW_NUMBER,RANK,LAG,LEAD,SUM/COUNTOVER), Set operations (UNION,INTERSECT,EXCEPT), TPC-H partial benchmarks, pgbench read-write support.
- highlights: Window functions v0 (
- 5.16 (closed) — Columnar Segment Format v0 (AngaraColumn prep):
- highlights: columnar segment on-disk format v0 + column cache + zone maps; baseline read-only scan surface; see evidence pack for closure notes.
- 5.15.13 (closed) — Page-Based Default + Overlay Hydrate Bridge:
- highlights: page-based storage default ON, hydrate bridge restores persistent tables on startup,
configurable
flush_on_commitfor snapshotted tables.
- highlights: page-based storage default ON, hydrate bridge restores persistent tables on startup,
configurable
- 5.15.12 (closed) — Txlog Path Guardrails & Regression Tests:
- highlights: regression tests for commit conflict 40001 (hotfix follow-up), runtime warning for split-directory misconfiguration, and risk closure.
- 5.13.1 (in_review) — AQP hardening fix release:
- 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.
- highlights: bounded async feedback ingest path, self-join-safe operator identity matching, and documented
AQP capacity knob (
- 5.15.11 (closed) — IR Executor Refactor + Unwrap/Expect Cleanup:
- note: no user-facing SQL/ops contract changes (refactor-only train; internal executor module decomposition
- guardrails).
- note: no user-facing SQL/ops contract changes (refactor-only train; internal executor module decomposition
- 5.12.3 (closed) — Comparative Benchmark Infrastructure:
- highlights: SQL-level benchmark suite (B1-B7), AngaraBase-vs-PostgreSQL comparator reports, SQL coverage corpus and score reporting, and optional nightly SQL benchmark hook.
- 5.12.2 (closed) — Parallel Performance Polish:
- highlights: removed sequential join-build merge bottleneck via shared partition build path; preserved join
accounting telemetry continuity in
EXPLAIN ANALYZE.
- highlights: removed sequential join-build merge bottleneck via shared partition build path; preserved join
accounting telemetry continuity in
- 5.12.1 (closed) — AngaraParallel gap closure:
- 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).
- highlights: partitioned parallel join build phase, settings-governed DOP caps
(
- 5.10.1 (closed) — AngaraVector gap closure:
- 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.
- highlights: execution mode contract aligned to
- 5.10 (closed) — AngaraVector phase-1:
- highlights: vector execution mode now covers join/aggregate plan paths and
EXPLAINmarks vector operators (VectorHashJoin,VectorAgg) when vector mode is active.
- highlights: vector execution mode now covers join/aggregate plan paths and
- 5.9 (closed) — AngaraVector phase-0:
- highlights: introduced vector batch format baseline (
batch_sizedefault 1024), scan/filter/project vector path, and bounded per-query vector memory budget knobs.
- highlights: introduced vector batch format baseline (
- 5.8.1 (closed) — AngaraMemory async snapshots + per-table scheduler:
- highlights:
durability='snapshotted'no longer performs immediate hot-path page persistence; checkpoint worker now honors per-tablecheckpoint_interval_msscheduling.
- highlights:
- 5.8 (closed) — AngaraMemory phase-1:
- highlights:
durability='logged'|'snapshotted', opt-ineviction_policy='fifo', and SQL-visible memory-table runtime counters insys.tables.
- highlights:
- 5.7 (closed) — AngaraMemory phase-0:
- highlights:
storage='memory'table surface, fail-closedmax_rowsenforcement (54023), and volatiledurability='none'restart semantics.
- highlights:
- 5.6.5 (closed) — reliability engineering closure:
- note: no user-facing SQL/ops contract changes (runtime panic-hardening + CI governance).
- 5.6.4 (closed) — architecture governance closure:
- note: no user-facing SQL/ops contract changes (layering/dependency CI guardrails).
- 5.6.3 (closed) — native packaging + secure init-first bootstrap:
- 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 (
- highlights:
- 5.6.2 (closed) — packaging baseline for operator install path:
- 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
- highlights:
- 5.6.1 (closed) — architecture hygiene patch:
- note: no user-facing SQL/ops contract changes (AngaraBook: no user-facing changes)
- 5.5 / 5.6 (closed) — advanced diagnostics + pilot validation:
- trains:
- 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 (
- 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 4.25/5.3/5.3.1/5.4 surfaces (RBAC/RLS/break-glass/audit/TDE/client-encrypted columns)
- pages:
- 5.4 (closed) — Security Layer Reinforcement Phase 2:
- 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
- highlights: Audit v1 DML policy controls (
- 5.3.1 (closed) — TDE patch for audit-at-rest:
- 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
- highlights: audit sink bytes are encrypted when TDE is enabled,
- 5.3 (closed) — TDE v0 baseline:
- 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
- highlights: fail-closed TDE enablement for page/WAL at-rest encryption,
- 5.2 (closed) — module decomposition phase-1 (
.inc.rselimination, security module layout, pgwire tests split, architecture doc consolidation) completed as refactor-only train:- note: no user-facing SQL/ops contract changes
- 5.1 (closed) — module decomposition phase-0 (
sys_catalog,virtual_catalog,metrics) completed as refactor-only train:- note: no user-facing SQL/ops contract changes
- 4.0 line (closed) — major-line closure completed with truth-of-now planning sync:
- 4.25.1 (closed) — Security Hardening & RLS Optimization:
- 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
- highlights: fail-closed IR RLS predicate checks (
- 4.25 (closed) — Security Reinforcement Phase 1:
- highlights: secure
--initsuperuser bootstrap, RLS v0 on reads+writes, break-glass lifecycle, audit chain verification,sys.*security introspection views/functions
- highlights: secure
- 4.21 (closed) — AngaraStat Level 2 reservoir stats (bounded):
- highlights:
stats_reservoir_size, Level 2 histogram/MCV surfaces insys.column_stats
- highlights:
- 4.22 (closed) — query diagnostics v0:
- highlights:
EXPLAIN/EXPLAIN ANALYZE, slow query log,angara_stat_activity,angara_stat_statements,angara_top_queries()
- highlights:
- 4.24 (closed) — reliability/efficiency hardening:
- highlights:
REINDEX INDEX, BRIN range-efficiency metric, strict storage startup default, no-auth startup guardrail
- highlights:
- 4.24.1 (closed) — mutation policy
no_delete:- highlights: unified
mutation_policy,42809guards for DELETE/TRUNCATE and PK/FK updates,sys.tables.mutation_policy
- highlights: unified
- 4.24.2 (closed) — SQL semantics/stats hardening:
- highlights: typed min/max streaming stats, mutation epoch metric, EXPLAIN ANALYZE dry-run for DML, wait-event classification
- 4.24.3 (closed) — SQL/stats closure:
- highlights: typed
col_min/col_maxsurfaces, typed reservoir samples with membership-aware UPDATE/DELETE handling,wait_event_typeinangara_stat_activity
- highlights: typed
- 4.24.4 (closed) — core decomposition for executor:
- highlights: internal refactor (
ir_executorsplit into scan/join/aggregate/sort modules), no user-facing SQL/ops contract changes
- highlights: internal refactor (
- 4.15 (closed) — BRIN baseline (bounded):
- 4.16 (closed) — page checksums v0 + verify-pages triage surface:
- 4.17 (closed) — SQL semantics tranche (bounded
WITH,ORDER BY <expr>, deterministic0A000hygiene): - 4.18 (closed) — table partitioning v0 (
RANGE/LIST, routing, pruning, per-partition cascade): - 4.19 (closed) — append-only table mode v0 (
append_onlyDDL/property,42809mutation guards, partition inheritance, rowid watermark): - 4.20 (closed) — AngaraStat Level 1 (
ndv_approx/min/max/null_count,stats_level_maxcontrols, stats observability): - 4.23 (closed) — unified
.adbstorage path for heap tables:- runtime routing fixed: user DB writes go to
<db>.adband<db>.atl(notbase.*) - backup/restore note updated:
operations/backup-and-restore.md
- runtime routing fixed: user DB writes go to
Milestones (testing-ready)
-
2.3 (closed) — backup/restore baseline is testable:
- runbook:
angarabook/src/operations/backup-restore.md
- runbook:
-
2.4 (closed) — execution/compat deepening is pinned:
- known issues remain explicit:
angarabook/src/operations/known-issues.md
- known issues remain explicit:
-
2.7 (closed) — backup/restore v2 phase 1a is testable (offline/local baseline):
- AngaraBook page:
operations/backup-and-restore.md
- AngaraBook page:
-
2.8 (closed) — validation hardening is testable:
-
2.9 (closed) — backup/restore v2 phase 1b (online/PITR) is testable:
- AngaraBook page:
operations/backup-and-restore.md
- AngaraBook page:
-
2.10 (closed) — SysCatalog identity + native
sys.*introspection is available:- identity file:
storage.data_directory/identity_v0.txt
- identity file:
-
2.11 (closed) —
pg_catalogsemantics are rooted in SysCatalog (trace-driven) + identity rehearsal gate:rehearsal_identity_rm211.sh)- compat matrix (truth source):
angarabook/src/operations/client-compatibility.md
- compat matrix (truth source):
-
2.12 (closed) — upgrade rehearsal is wired into nightly discipline + docs anti-drift is enforced:
- docs validator:
docs/validate-docs.sh
- docs validator:
-
2.13 (closed) — code health hardening: prevent god-files growth (touched-file budget gate):
-
2.14 (closed) — admin remote transport v0 (TCP) +
angara-cliremote identity:- server: env
ANGARABASE_ADMIN_ADDR+crates/angarabased/src/admin_tcp.rs - client:
angara-cli admin identity --addr <host:port> [--json]
- server: env
-
2.15 (closed) — persisted SysCatalog v0: DDL survives restart:
- persisted catalog file:
storage.data_directory/sys_catalog_v0.txt
- persisted catalog file:
-
2.16 (closed) — graceful shutdown contract (bounded):
- env knob:
ANGARABASE_SHUTDOWN_TIMEOUT_MS
- env knob:
-
2.17 (closed) — admin/ops via pgwire (SQL/sys.*, no Unix sockets):
- sys views:
sys.identity,sys.health,sys.settings - optional SQL shutdown (fail-closed):
ANGARABASE_ALLOW_SQL_SHUTDOWN=1+SELECT sys.request_shutdown()
- sys views:
Released tags
Список released tags и ссылки на release notes см. в CHANGELOG.md → “Released”.