Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

AngaraBase

Реляционная СУБД с протоколом PostgreSQL и предсказуемым поведением. Написана на Rust. Текущая ветка — 0.6.x.

Rust PostgreSQL pgwire MVCC · UNDO-log Soft Launch · v0.6.x

AngaraBase разработана для нагрузок типа ERP/SaaS, где предсказуемость важнее «магии», а каждое поведение фиксируется явным контрактом.

Что описывает эта документация

Здесь — то, что уже работает в коде на текущей ветке. Roadmap-фичи помечены отдельно. AngaraBase — молодой проект, и мы предпочитаем точность маркетинговым обещаниям.


С чего начать

Выберите вход по своей роли:

Кто выКуда идти
Знакомлюсь с продуктомЧто такое AngaraBaseАрхитектура с высоты птичьего полёта
Хочу попробовать локальноQuickstart за 5 минут
Разработчик приложенияSQL compatibilityData typesKnown issues
DBA / SREInstallationConfigurationBackup/RestoreOperations runbooks
Security engineerSecurity modelHardeningAudit
Contributor / ResearcherArchitecture overviewLayering and BoundariesGlossary
Сообщаю о проблеме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.

Многоуровневая защита с явными контрактами

Безопасность встроена в ядро, а не «прикручена» сверху. Шесть слоёв защиты, каждый с собственным контрактом:

  1. Транспорт и идентичность — TLS, SCRAM, cert-аутентификация.
  2. RBAC — кому вообще разрешено.
  3. RLS v1 — какие строки видны и изменяемы.
  4. Break-glass — единственный путь обхода RLS (даже SUPERUSER его не имеет), всегда с REASON, TTL и аудитом.
  5. Audit chain — append-only, tamper-evident (SHA-256 chain).
  6. 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)

SQL Reference (Reference)

Безопасность (How-to)

Эксплуатация (How-to)

Operator deep-dives — runbooks (Reference)

Architecture (Reference)

Справочник (Reference)

История изменений


Сообщество и участие

Мы рады участникам сообщества:

  • Нашли баг или 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"
СтекДрайверСтатус
Pythonpsycopg2, psycopg3Поддерживается
Node.jspg (node-postgres)Поддерживается
JavaPostgreSQL JDBCПоддерживается
Golib/pq, pgxПоддерживается
.NETNpgsqlПоддерживается
Toolingpsql, DBeaverПоддерживается с оговорками — см. Client compatibility

Полный compat-контракт и smoke-сценарии: SQL compatibility overview.

Чем AngaraBase отличается от PostgreSQL

ОбластьPostgreSQLAngaraBase
Pluggable storageВ работе (pg_am v2)Встроено: row-store + AngaraMemory; AngaraColumn — в roadmap
MVCCUNDO-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Доступен
AngaraPlanCost-based оптимизатор запросовДоступен
AngaraFlowStreaming-исполнение запросов (iterator/Volcano модель)Доступен
AngaraIOAsync I/O pipeline (storage, WAL, prefetch)Доступен
AngaraGCMVCC garbage collection (очистка устаревших версий строк)Доступен
AngaraVectorVectorized execution (SIMD-оптимизация)Доступен
AngaraParallelПараллельное выполнение запросовДоступен
AngaraMemoryIn-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-кодом, а не неожиданный результат. Это предсказуемо и безопасно для продакшена.


Дополнительные материалы

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 (каталог) должны сохраняться между перезапусками.

  1. Остановите сервер (Ctrl+C).
  2. Запустите снова: angarabase-server --config-path ./angarabase.conf.
  3. Убедитесь, что таблица на месте:
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; пользователю без прав — отказ.

Если что-то не так

Дальше

После того как сервер ответил на psql -h 127.0.0.1 и базовый SELECT отработал, логичные следующие шаги:

Подключение клиентов: psql, Python, JDBC

Что вы получите за 15 минут

После этого туториала у вас будут три рабочих способа подключения к локально запущенному инстансу AngaraBase:

  1. psql — интерактивная консоль PostgreSQL.
  2. Python через psycopg[binary] — типичный скрипт приложения.
  3. 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.

Дальше

Контракты в AngaraBase

Goal

Объяснить, что в AngaraBase понимается под словом «контракт», какие уровни контрактов существуют и какими механизмами они соблюдаются. Эта страница — для пользователей, DBA и новых контрибьюторов: чтобы при чтении документации, кода или сообщений об ошибках было понятно, на какие гарантии можно полагаться, а какие — явно вне контракта.

Что мы понимаем под контрактом

Контракт в AngaraBase — это явное обещание о наблюдаемом поведении компонента: что он принимает на вход, что возвращает, какие гарантии даёт и как ведёт себя при нарушении границ. Контракт не «лучшие намерения» и не «как обычно работает» — это формализованная договорённость, которую обязаны соблюдать обе стороны: реализация и вызывающий код (или клиент).

У контракта три ключевых свойства:

  1. Явность. Контракт зафиксирован в одном каноническом источнике — не в чате, не в коде комментария, не в «общем понимании команды».
  2. Проверяемость. Соблюдение контракта подтверждается автоматически: тестами, типами, метриками, lint-проверками.
  3. 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 его раскроет.

Хранение данных (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
.adbHeap-страницы с данными таблиц и индексами. Самодостаточный per-database storage file.APG1
.atlTransaction 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-конвейеров и без влияния на транзакционную производительность.

Связанные разделы

Концепции (что почитать дальше)

How-to (что сделать)

Справочник

Транзакции и 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_commitEpoch (commit timestamp), при котором версия была создана
deleted_commitEpoch, при котором версия была помечена как удалённая ( для активных версий)

Правило видимости

Версия строки видна транзакции со snapshot S, если выполняются оба условия:

  1. created_commit <= S — версия создана до или в момент snapshot
  2. Версия не удалена, или 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 отвечает за их очистку.

Механизм работы

  1. GC watermark — вычисляется как минимальный snapshot среди всех активных транзакций: min(active_snapshots)
  2. Версии строк с deleted_commit < watermark безопасны для удаления — ни одна активная транзакция не может их увидеть
  3. Очистка выполняется фоновым процессом без остановки обработки запросов
  4. Bounded slices — GC обрабатывает данные порциями фиксированного размера, чтобы не вызывать всплески задержки
  5. 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).

Что восстанавливается

  1. Committed transactions — транзакции, которые успели записать COMMIT в WAL
  2. Aborted transactions — незавершённые транзакции помечаются как aborted
  3. MVCC visibility — информация о том, какие версии строк видны для каждого commit epoch
  4. Transaction counters — текущий commit epoch и другие счётчики

Процесс восстановления

  1. WAL scan — сканирование файлов transaction log в хронологическом порядке
  2. MVCC replay — восстановление in-memory структур MVCC из записей в WAL
  3. 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

Связанные разделы

Индексы (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);

Поддерживаемые типы ключей:

ТипАлиасы
INTEGERint, int4
BIGINTint8
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-страницы:

  1. Запрос обращается к индексу → получает набор TID.
  2. По каждому TID читается heap-страница.
  3. 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 mutationsIn-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).

Связанные разделы

Концепции (что почитать дальше)

How-to (что сделать)

  • DDL: CREATE/DROP INDEX — синтаксис создания и удаления индексов.
  • Диагностика — как через EXPLAIN ANALYZE и sys.* понять, используется ли индекс.

Справочник

Обработка запросов (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 pathFull table scan, B+tree index scan, BRIN scan
Join methodHash 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

КолонкаОписание
ndvNumber of distinct values (HyperLogLog)
min_value / max_valueГраницы диапазона значений
null_countКоличество NULL-значений
histogramРаспределение значений (equi-height histogram)
mcvMost 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 и параллельное исполнение

КомпонентОписаниеСтатус
AngaraVectorVectorized/SIMD execution — обработка batch по колонкам вместо row-at-a-time (execution.vector_batch_size)Доступно (bounded)
AngaraParallelMorsel-driven parallelism — параллельное выполнение на нескольких ядрах (sql.parallel.dop_cap_*)Доступно (bounded)
AngaraAdaptAdaptive processing — переключение стратегий во время выполненияВ roadmap

Связанные разделы

Концепции (что почитать дальше)

How-to (что сделать)

  • ДиагностикаEXPLAIN ANALYZE, slow-query log, как читать план.
  • Tracing — распределённая трассировка фаз parse → plan → execute.
  • ЛогированиеANGARABASE_LOG_QUERY_TEXT, ANGARABASE_LOG_MIN_DURATION_MS.

Справочник

Системный каталог и метаданные

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');

Связанные разделы

Жизненный цикл инстанса

Как AngaraBase понимает «кто владеет этими файлами данных»: идентичность инстанса, аренда (Instance Lease) и порядок запуска. Аренда — это то, что даёт безопасное восстановление после аварии и переносимость хранилища между хостами без дампа/восстановления.

Идентичность инстанса

При инициализации инстанс получает устойчивую идентичность:

  • cluster_id — UUID логического кластера БД.
  • instance_id — UUID конкретного инстанса.
  • Каталог данных и каталог журнала транзакций — физическое расположение файлов.

Идентичность хранится в двух местах, чтобы пережить как сбой файла, так и сбой каталога:

  1. VERSION-маркер — бинарный файл с версией формата и идентификаторами.
  2. Страницы системного каталога — в зарезервированных страницах base.adb с полными метаданными.

Аренда инстанса (Instance Lease)

Аренда не даёт двум инстансам одновременно писать в одни и те же файлы — а это прямой путь к повреждению данных. Запись аренды лежит в SysCatalogMetaV0 внутри страниц base.adb и обновляется атомарно полным образом страницы. Поэтому механизм работает на NFS/SAN, где flock() ненадёжен.

Что записано в аренде

ПолеНазначение
holder_idUUID инстанса-владельца
acquired_at_unix_sкогда аренда взята (Unix-время, с)
expires_at_unix_sкогда истекает (TTL)
holder_pidPID процесса (диагностика)
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.

Порядок запуска

  1. Pre-flight — каталог данных существует и инициализирован, VERSION-маркер совместим, размер страницы совпадает со сборкой бинаря.
  2. Захват аренды — загрузка системного каталога из base.adb, затем:
    • аренды нет → захватить сразу;
    • аренда истекла → перехватить (с предупреждением в лог);
    • аренда активна → fail-closed с информативной ошибкой (см. ниже);
    • принудительный перехват → переопределить активную аренду (опасно).
  3. Восстановление — проигрывание WAL (backend file_bin), восстановление in-memory состояния MVCC, запуск heartbeat.
  4. Готов к подключениям — поднимаются слушатели (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повреждённый журнал транзакцийпроверить ФС, при необходимости восстановиться из бэкапа

Безопасность: аренда не аутентифицирует — права доступа ФС и сетевые ограничения по-прежнему обязательны, особенно на разделяемом хранилище.

Связанные разделы

Концепции

How-to

Справочник

Обзор совместимости 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 и COLLATE0A000; неверный 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 CTE0A000 (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 JOIN0A000
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.mdStable
DDL (CREATE, ALTER, DROP)ddl.mdStable
DML (INSERT, UPDATE, DELETE)dml.mdStable
Запросы (CTE, JOIN, ORDER BY)queries.mdStable
Секционирование таблицpartitioning.mdBaseline

Ключевые DDL-границы: CREATE MATERIALIZED VIEW поддержан, обычный CREATE VIEW — planned (0A000), CREATE TRIGGER — non-goal (0A000), FOREIGN KEY — принимается как NOT ENFORCED.

Коды ошибок (SQLSTATE) — быстрый справочник

SQLSTATEИмяТипичный сценарий
0A000feature_not_supportedWITH RECURSIVE, JOIN … USING/NATURAL, NTILE, именованные окна, DISTINCT ON, обычный CREATE VIEW (planned), CREATE TRIGGER (non-goal), сложные RLS-предикаты
54000program_limit_exceededCROSS JOIN сверх бюджета sql.join.max_cross_join_rows (деф. 1 000 000)
23514check_violationроутинг секций: нет подходящей партиции и нет DEFAULT
42809wrong_object_typeUPDATE/DELETE на append-only; PK/FK update под no_delete
22023invalid_parameter_valueневерный stats_level_max, break-glass TTL, setval вне [MINVALUE..MAXVALUE]
42501insufficient_privilegeнет ролей для security-операций, нет SecurityContext
25001active_sql_transactionSET SESSION CONTEXT внутри активной транзакции
42P10invalid_column_referenceORDER BY по номеру вне диапазона колонок
2200Hsequence_generator_limit_exceedednextval за MAXVALUE/MINVALUE без CYCLE
55000object_not_in_prerequisite_statecurrval(seq) до первого nextval в этой сессии
42P07duplicate_objectCREATE SEQUENCE существующего имени без IF NOT EXISTS
42P01undefined_tableDROP SEQUENCE / nextval / currval / setval несуществующей последовательности
428C9generated_alwaysINSERT явного 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 (secondmillennium); неизвестное поле → 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_rowStable всегда строчный исполнитель;
  • force_vectorExperimental 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УровеньЗаметки
BOOLEANBOOL16StableTRUE / FALSE / NULL
SMALLINTINT221Baseline16-бит знаковое
INTEGERINT, INT423Stable32-бит знаковое
BIGINTINT820Stable64-бит знаковое
REALFLOAT4700BaselineОдинарная точность
DOUBLE PRECISIONFLOAT8701StableДвойная точность
NUMERICDECIMAL1700BaselineТочное число (Decimal-backed); строгий парс при явном cast
TEXT25StableСтрока переменной длины
VARCHAR(n)CHARACTER VARYING1043BaselineСтрока с лимитом (text-backed)
CHAR(n)BPCHAR, CHARACTER1042BaselineСтрока фиксированной длины (text-backed)
MVARCHAR(n)46001Baseline1С-совместимый национальный VARCHAR: UTF-16LE-семантика, сравнение без учёта регистра и хвостовых пробелов, своя нормализация ключа индекса
BYTEA17StableДвоичная строка переменной длины
UUID2950BaselineТолько явные приведения; невалидный текст → 22P02
DATE1082BaselineText-backed; минимальная валидация
TIMESTAMP1114BaselineДата-время без таймзоны (text-backed)
TIMESTAMPTZ1184BaselineПарсится для 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 typepg_oidСтатус
TIME1083Planned
INTERVAL1186Planned
JSON114Planned (функции json_agg / json_build_object возвращают text)
JSONB3802Planned

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 LAST0A000

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

OptionValuesDefaultDescription
append_onlytrue / falsefalseReject UPDATE/DELETE (SQLSTATE 42809)
mutation_policyunrestricted / append_only / no_deleteunrestrictedFine-grained mutation control
stats_level_max030Max statistics collection level
stats_reservoir_size≥ 1Engine defaultReservoir 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 TRIGGERnon-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 EXISTS42P07
DROP SEQUENCE несуществующего имени без IF EXISTS42P01
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

TypeAliases
intint4, integer
bigintint8
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 FK0A000
Обычный CREATE VIEW (Planned)0A000
CREATE TRIGGER (non-goal)0A000
Составной / expression индекс0A000
Неподдерживаемый index method0A000
stats_level_max вне [0..3]22023

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

currvalsession-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 table42809
DELETE/TRUNCATE under no_delete42809
PK/FK UPDATE under no_delete42809
Insert into partitioned table, no matching partition23514
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-NULL428C9
INSERT ... ON CONFLICT (a, b) (multi-column target)0A000
INSERT ... ON CONFLICT ON CONSTRAINT <name>0A000

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 RECURSIVE0A000 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

FormSQLSTATE
WITH RECURSIVE0A000
Data-modifying CTEs (WITH … INSERT/UPDATE/DELETE)0A000
DISTINCT ON (...)0A000
NTILE, именованные окна (WINDOW-clause)0A000
JOIN … USING (...) / NATURAL JOIN0A000
ORDER BY ... NULLS FIRST|LAST, COLLATE0A000

AngaraStat surfaces

Встроенные статистические представления — то, на что опирается планировщик при оценке кардинальности. Полезны, чтобы понять, по каким колонкам собрана статистика (histogram/MCV/HLL) и насколько она свежа (*_epoch); пустые histogram/MCV означают, что для колонки ещё не набран Level 2.

sys.table_stats

ColumnDescription
stats_level_maxMax collection level configured
last_committed_rowidLast committed row ID
last_insert_epochEpoch of last insert
last_mutation_epochEpoch of last mutation

sys.column_stats

ColumnDescription
ndv_approxApproximate number of distinct values (HLL)
col_minColumn minimum (typed Value)
col_maxColumn maximum (typed Value)
null_countNumber of NULLs
stats_epochStats collection epoch
hll_enabledWhether HLL tracking is active
histogram_boundsEqui-depth histogram boundaries (Level 2)
mcv_valuesMost common values (Level 2)
mcv_frequenciesMCV frequencies (Level 2)
reservoir_sizeReservoir sample size (Level 2)
reservoir_epochReservoir epoch (Level 2)
reservoir_drift_countDrift 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 CTE0A000
DISTINCT ON, NTILE, именованные окна0A000
ORDER BY ... NULLS FIRST|LAST / COLLATE0A000
JOIN ... USING (...) / NATURAL JOIN0A000
CROSS JOIN сверх бюджета строк54000
ORDER BY ordinal out of range42P10
Expression type error42883

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 DEFAULT23514
Hash partitioning0A000
Multi-column partition key0A000
Subpartitioning0A000
Disable append-only on child (parent is append-only)42809

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 SUPERUSER cannot.
  • Activation requires a mandatory REASON and TTL.
  • 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|denylist per 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.
  • DETERMINISTIC mode allows equality predicates; RANDOMIZED rejects server-side predicates (0A000).

See encryption.md for the SQL surface and operator rules.

How features work together

CombinationBehaviour
RBAC + RLSRBAC decides “is this operation allowed at all”; RLS further restricts “which rows”.
Break-glass + auditTemporary elevation is accepted only with a reason and full traceability in the audit chain.
TDE + auditWhen TDE is enabled, audit bytes on disk are encrypted; sys.audit_log remains readable only with the correct key.
Client encryption + SQL boundsDeterministic 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.settings shows security knobs without secrets.
  • Security functions return data (or empty results) without internal errors.
  • Unsupported operations terminate with an explicit SQLSTATE (0A000, 42501, or 22023) — never a silent bypass.

Troubleshooting

  • 42501 insufficient_privilege on security DDL/ops Check user roles and session context; see authorization.md.
  • 0A000 feature_not_supported in 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.

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 scram or cert modes 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:

ModeWhen to useIdentity proof
trustLocal development / testing onlyNone — any connecting client is accepted
scramProduction and stagingSCRAM-SHA-256 password challenge
mtlsmTLS environmentsClient 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:

  • trust mode on a non-loopback bind address requires the explicit flag --allow-insecure-no-auth.
  • Without this flag the server refuses to start (fail-closed).
  • scram or cert modes 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 scram mode, unauthenticated connections are rejected.
  • In cert mode, clients without a valid certificate are rejected.
  • trust on remote bind without --allow-insecure-no-auth prevents startup.
  • sys.settings confirms 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/cert or pass --allow-insecure-no-auth for development.
  • authentication failed for user "..." on connect Verify the password or certificate; check that auth.mode matches the client’s auth method.
  • TLS handshake failure Confirm cert_path and key_path point to valid, non-expired files; verify the client’s sslmode setting.
  • Init refused: scram requires password Provide --superuser-password (or --superuser-password-file) when --auth-mode scram is set.
  • Need a bug-report artifact? See ../reference/support.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 SUPERUSER or SECURITY_ADMIN privileges.
  • 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

OperationBehaviour
SELECTRows that fail the predicate are silently excluded.
INSERTThe new row must satisfy the predicate; otherwise an error is raised.
UPDATEThe old row must be visible (silent skip if not); the new row must satisfy the predicate (error if not).
DELETEThe 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:

MaskEffect
partialReturns a stable masked shape of the original value.
nullifyReturns 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_policies reflects active policies, mask metadata, and provenance.
  • Unsupported paths return a deterministic SQLSTATE, never a silent bypass.

Troubleshooting

  • 42501 insufficient_privilege The current user lacks the required role or grant. Check sys.my_privileges and angara_user_roles().
  • 0A000 feature_not_supported on 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 POLICY with a USING predicate to allow the intended rows.
  • Need a bug-report artifact? See ../reference/support.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_ADMIN or SUPERUSER privileges (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 categoryv0 (baseline)v1
Auth (success / failure / disconnect)YesYes
DDL (CREATE / ALTER / DROP)YesYes
DCL (GRANT / REVOKE)YesYes
User / role managementYesYes
Security policy changesYesYes
Break-glass lifecycleYesYes
DML (SELECT / INSERT / UPDATE / DELETE)NoYes (policy-driven)
Key operationsNoYes

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
ModeBehaviour
offNo DML events recorded (default).
allowlistRecord DML only for listed schema.table entries — targeted compliance.
denylistRecord 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_log decrypts 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() returns is_valid = true for an intact chain.
  • sys.audit_log shows auth, DDL, DCL, policy, and break-glass events.
  • With DML policy set to allowlist or denylist, matching DML operations appear in the audit log.
  • TDE-encrypted audit files are unreadable without the master key.

Troubleshooting

  • angara_audit_verify_chain() returns is_valid = false The chain has been tampered with or corrupted. Note the first_broken_seq and 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 is off. 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_HEX and 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.

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 .adb data 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
VariablePurpose
ANGARABASE_TDE_ENABLE1 to enable; unset or 0 to disable.
ANGARABASE_TDE_MASTER_KEY_HEX256-bit key in hex (64 characters). Never appears in sys.settings or logs.
ANGARABASE_TDE_MASTER_KEY_IDHuman-readable, non-secret key identifier (visible in sys.settings).
ANGARABASE_TDE_LAST_ROTATION_UNIXUnix timestamp of the last key rotation (metadata only).

Fail-closed behaviour

  • If ANGARABASE_TDE_ENABLE=1 and 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

FieldContent
enc.algAlgorithm identifier (whitelisted).
enc.modedeterministic or randomized.
enc.key_idOpaque, non-secret key identifier.
payloadCiphertext bytes — never interpreted by the server.

The server never accepts raw key material via SQL, environment variables, config, logs, or sys.* views.

Operator rules

ModeAllowed operationsRejected operations
DETERMINISTICEquality predicates (=, !=, IN)Range, LIKE, aggregation, ordering
RANDOMIZEDNone (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.settings and diagnostics expose only key_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.settings shows security.tde_enabled = true and the key_id without 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_supported on encrypted column query The query uses an unsupported operator for the column’s encryption mode. For RANDOMIZED columns, only read/write is allowed. For DETERMINISTIC, 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.settings does not show TDE knobs Ensure ANGARABASE_TDE_ENABLE=1 is set in the environment before server startup.
  • Need a bug-report artifact? See ../reference/support.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_GLASS capability.
  • 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_query audit 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

VariableDefaultDescription
ANGARABASE_SECURITY_BREAK_GLASS_MAX_TTL24hMaximum allowed TTL for any break-glass session. Requests exceeding this are rejected.

Audit trail

All break-glass lifecycle events are recorded:

Event typeWhen
break_glass_activateSET BREAK_GLASS succeeds.
break_glass_queryEvery query while break-glass is active.
break_glass_deactivateRESET BREAK_GLASS is called.
break_glass_expireTTL elapses without manual deactivation.

Invariants

  1. Audit must be healthy. If the audit subsystem is down or corrupted, break-glass activation fails (fail-closed).
  2. TTL is mandatory. SET BREAK_GLASS without TTL → error.
  3. Reason is mandatory. SET BREAK_GLASS without REASON → error.
  4. Max TTL is server-enforced. Exceeding ANGARABASE_SECURITY_BREAK_GLASS_MAX_TTL22023 invalid_parameter_value.
  5. No refresh. A client cannot extend the TTL — deactivate and re-activate with a new reason/TTL instead.
  6. SUPERUSER ≠ RLS bypass. Only BREAK_GLASS bypasses RLS.

Expected result

  • SET BREAK_GLASS with valid reason and TTL activates bypass; angara_break_glass_status() confirms.
  • All queries during break-glass appear in sys.audit_log with event_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_value on SET BREAK_GLASS The TTL exceeds ANGARABASE_SECURITY_BREAK_GLASS_MAX_TTL or is in an invalid format. Check the max TTL setting and use a supported duration format ('15m', '2h', '1d').
  • 42501 insufficient_privilege on SET BREAK_GLASS The current user has not been granted BREAK_GLASS. A SECURITY_ADMIN must run GRANT BREAK_GLASS TO <user>.
  • Break-glass activation fails with “audit unavailable” The audit subsystem must be healthy. Check ANGARABASE_AUDIT_LOG_PATH and 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.

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 (scram or cert) — not left as trust for production.
  • TDE enabled with valid key material.
  • Audit log path set and writable.
  • DML audit policy chosen deliberately (off, allowlist, or denylist).
  • 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.settings shows 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/cert mode.

Troubleshooting

  • Server does not start after enabling TDE Verify ANGARABASE_TDE_MASTER_KEY_HEX is 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.enabled must be true or --allow-insecure-no-auth must be passed (dev only). Check tls.require_on_remote_bind and server.host.
  • DML audit events missing Verify audit.dml_mode is not off and that the target table matches the allowlist/denylist entries. Table names must be fully qualified (schema.table).
  • angara_audit_verify_chain() returns is_valid = false The audit chain is corrupted. Note the first_broken_seq and 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.

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

Чек-лист:

  1. В выводе есть Cipher : GOST2012-GOST8912-GOST8912 (или другой ГОСТ-набор).
  2. Protocol : TLSv1.2.
  3. Handshake завершается успешно.

Через SQL (если клиент поддерживает):

SELECT name, value FROM sys.settings WHERE name LIKE 'tls.%';
-- Проверьте, что tls.gost_enabled = 'true'

Шаг 4. Проверка fail-closed (негативные тесты)

Убедитесь, что сервер отказывается стартовать при сломанном окружении.

  1. Нет провайдера. Временно отключите ГОСТ-движок (переименуйте библиотеку или измените конфиг OpenSSL) и запустите с ANGARABASE_TLS_GOST_ENABLED=1. → Ожидается: отказ старта с «GOST provider not available».
  2. Невалидный набор шифров. ANGARABASE_TLS_GOST_CIPHER_SUITES="INVALID-CIPHER". → Ожидается: отказ старта с ошибкой конфигурации.
  3. 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-сценарии вам нужны:

Установка

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

Компилируемый дефолт backendnoop (без 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 сервер создаёт и поддерживает:

ArtifactPurpose
VERSIONInitialization marker (format_version, min_server_version); enforces fail-closed startup.
base.adbOn-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

VariableDefaultDescription
ANGARABASE_SHUTDOWN_TIMEOUT_MS1000Bounded graceful-shutdown timeout (ms).
ANGARABASE_ALLOW_SQL_SHUTDOWNoffAllow shutdown trigger via SELECT sys.request_shutdown().
ANGARABASE_STORAGE_STRICT_STARTUPenabledStorage verification on startup. Set 0/false/off to disable.
ANGARABASE_METRICS_ADDROverride for [ops].metrics_addr.
ANGARABASE_SUPPORT_CONTACThttps://github.com/angarabase/angarabase/issuesSupport 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_TABLE100000Default hard cap for storage='memory' tables when max_rows is omitted. Must be positive.

TLS knobs

VariableDefaultDescription
ANGARABASE_TLS_ENABLEoffEnable TLS upgrade via pgwire SSLRequest.
ANGARABASE_TLS_CERT_PATHPEM certificate chain (required when TLS enabled).
ANGARABASE_TLS_KEY_PATHPEM private key (required when TLS enabled).

Transaction log knobs

VariableDefaultDescription
ANGARABASE_TRANSACTION_LOGOverride txlog backend (noop / file / file_bin).
ANGARABASE_TRANSACTION_LOG_DURABILITYOverride durability (strict / relaxed / group_commit).
ANGARABASE_TRANSACTION_LOG_FSYNCOverride fsync for strict mode (0 / 1).

WAL (Write-Ahead Log) knobs

VariableDefaultDescription
ANGARABASE_WAL_VLF_ENABLEenabledEnable VLF (Virtual Log Files) circular layout. Set 0 to disable and use linear WAL.
ANGARABASE_WAL_MAX_SIZE_MB512Maximum WAL file size in MB. Controls circular buffer size for VLF.
ANGARABASE_WAL_VLF_SIZE_MB32Individual VLF segment size in MB. Must be smaller than WAL_MAX_SIZE_MB.
ANGARABASE_WAL_INIT_VLFS2Initial number of VLF segments to allocate at startup.

Diagnostics / slow-query knobs

VariableDefaultDescription
ANGARABASE_LOG_MIN_DURATION_MS-1 (disabled)Slow-query log threshold in milliseconds.
ANGARABASE_LOG_QUERY_TEXT0Include raw SQL text in slow log (0 / 1).
ANGARABASE_STAT_STATEMENTS_MAXMax in-memory entries for angara_stat_statements (LRU bounded).

Optimizer planning knobs

VariableDefaultDescription
ANGARABASE_OPTIMIZER_PLANNING_TIMEOUT_MS0CBO 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_ms0Settings surface alias for optimizer planning timeout; reflected in sys.settings when configured.

Vector execution knobs

VariableDefaultDescription
ANGARABASE_SQL_EXECUTION_MODEautoExecution 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_SIZE1024Vector batch size (1..1024), mostly useful for tests and diagnostics.
ANGARABASE_QUERY_MEMORY_LIMIT_MB256Per-query vector memory budget; exceeding the limit fails closed with SQLSTATE 53100 (no OOM fallback).

Parallel execution governance knobs

VariableDefaultDescription
ANGARABASE_PARALLEL_DOP_CAP_GLOBALCPU coresGlobal upper bound for SQL parallel workers.
ANGARABASE_PARALLEL_DOP_CAP_QUERYCPU coresPer-query upper bound for SQL parallel workers. Effective DOP is capped by both values.

Adaptive query processing knobs

VariableDefaultDescription
ANGARABASE_AQP_ENABLED1Global AQP switch for advisory feedback learning/apply.
ANGARABASE_AQP_MODEconservativeAQP mode (conservative / aggressive); conservative keeps correction hysteresis.
ANGARABASE_AQP_MIN_QUERY_TIME_MS100Minimum query runtime eligible for feedback observation.
ANGARABASE_AQP_LEARNING_RATE0.1EMA learning rate used for correction updates.
ANGARABASE_AQP_MAX_CORRECTION100.0Upper correction multiplier bound (guardrail against outliers).
ANGARABASE_AQP_VARIANCE_THRESHOLD10.0If variance exceeds threshold, correction entry is marked unstable and ignored.
ANGARABASE_AQP_CORRECTION_CACHE_MB64In-memory correction cache budget.
ANGARABASE_AQP_STORE_CAPACITY_MB1024Total bounded advisory store capacity; overflow evicts deterministic low-value entries.

OpenTelemetry tracing knobs

VariableDefaultDescription
ANGARABASE_OTEL_ENABLED0Enable OTel-style query span export (0 / 1).
ANGARABASE_OTEL_SAMPLE_RATE_PPM1000000Sampling in parts-per-million (0..1000000).
ANGARABASE_OTEL_EXPORTERstderrExport sink (stderr / file).
ANGARABASE_OTEL_ENDPOINTExport target for file exporter (JSONL path).

See also Diagnostics for query performance analysis.

Authentication knobs

VariableDefaultDescription
ANGARABASE_AUTH_MODEAuth 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

VariableDefaultDescription
ANGARABASE_SECURITY_BREAK_GLASS_MAX_TTL86400Max allowed break-glass TTL in seconds.

Audit knobs

VariableDefaultDescription
ANGARABASE_AUDIT_LOG_PATHPath to append-only audit sink file (JSONL + chain-hash fields).
ANGARABASE_AUDIT_MAX_BYTES4194304 (4 MiB)Rotation threshold for audit sink.
ANGARABASE_AUDIT_DML_MODEoffAudit policy for DML (off / allowlist / denylist).
ANGARABASE_AUDIT_DML_ALLOWLISTCSV schema.table list for audited DML (allowlist mode).
ANGARABASE_AUDIT_DML_DENYLISTCSV schema.table list excluded from audit (denylist mode).
ANGARABASE_AUDIT_EXPORT_JSON_ENABLED0Enable JSON export worker.
ANGARABASE_AUDIT_EXPORT_SYSLOG_ENABLED0Enable syslog export worker.
ANGARABASE_AUDIT_EXPORT_RATE_LIMIT_RPSExport rate limit in records/second (bounded).

AngaraIO v2 I/O Scheduler knobs

VariableDefaultDescription
ANGARABASE_IO_URING_QUEUE_DEPTH_LOWentries/4Low-priority I/O queue depth. Controls backpressure for non-critical operations. Clamped to 1–16384.
ANGARABASE_IO_URING_BATCH_MAX16Maximum 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

VariableDefaultDescription
ANGARABASE_TDE_ENABLE0Enable TDE v0 for page/WAL at-rest encryption.
ANGARABASE_TDE_MASTER_KEY_HEXMaster key bytes in hex (64 chars; secret; required when TDE enabled).
ANGARABASE_TDE_MASTER_KEY_IDNon-secret key identifier visible in sys.settings.
ANGARABASE_TDE_LAST_ROTATION_UNIXNon-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 (значения и источники)

Нерешённое — в Известных ограничениях и Поддержке.

См. также

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 на произвольный LSNphase 1b: full-online + log + restore-chain
Бэкап с центрального узла без SSH к БДлюбой из выше — через Admin API (--addr)

Для новых развёртываний по умолчанию — phase 1b (онлайн + PITR). Phase 1a — когда достаточно простого offline-снимка. Legacy shell-обёртки оставлены для совместимости.

Флаг конфигурации у angara-cli--config / -cangarabase-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).

  1. Copy storage.data_directory and storage.transaction_log_directory.
  2. After restore, run the txlog-level oracle.
  3. 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>.adb and <db>.atl.
  • heap_store/ is not the source of truth after migration.
  • Upgrading old instances may take time proportional to heap_store volume.
  • 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

CommandPurpose
backup fullOffline FULL backup to a single file.
backup inspectRead manifest only (no payload scan).
backup verifyStruct/hash integrity check (binary answer).
backup restoreLocal 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

CommandPurpose
backup full-onlineOnline FULL boundary (best-effort, with backup fence).
backup logWAL chunk by LSN range (strictly contiguous chain).
backup chain-validateBinary validation of the full chain.
backup restore-chainPITR 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

SymptomAction
Restore fails with TDE errorEnsure the same ANGARABASE_TDE_MASTER_KEY_HEX is set. See Configuration — TDE knobs.
Chain validation failsLSN boundaries between FULL and LOG chunks must be contiguous. Re-take the LOG chunk from the correct start LSN.
Oracle reports mismatchThe txlog replay-pages oracle is best-effort. Collect artifacts and file a report via Support.
heap_store migration slow after restoreExpected 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 — можно остановить инстанс на время копирования

Пошаговая инструкция

  1. Остановить source инстанс:
# Graceful shutdown для освобождения lease
kill -TERM <angarabase-pid>

# Дождаться завершения
ps aux | grep angarabase-server
  1. Проверить освобождение lease (опционально):
-- На другом инстансе или через backup connection
SELECT lease_holder_id FROM sys.identity;
  1. Скопировать файлы данных:
# Копировать 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 {} \;
  1. Запустить на target хосте:
# Обновить конфигурацию если нужно
vim /target/angarabase.conf

# Запустить AngaraBase
angarabase-server --config-path /target/angarabase.conf
  1. Проверить миграцию:
-- Проверить 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 migrationBackup/restore
DowntimeВремя копирования файловВремя backup + restore
Disk space1x (только target)2x (backup + target)
NetworkПрямое копированиеЧерез backup storage
ComplexityНизкаяСредняя
Point-in-timeТолько текущее состояниеЛюбой LSN

См. также

Подробные инструкции по host migration: 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:

  1. Stop the server (if running):
# Graceful shutdown releases the lease automatically
kill -TERM <angarabase-pid>
  1. Start normally:
angarabase-server --config angarabase.conf
  1. 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

  1. Stop the source instance:
# Graceful shutdown to release lease
kill -TERM <angarabase-pid>

# Verify shutdown completed
ps aux | grep angarabase-server
  1. Verify lease is released:
# Check that no process holds the lease
# (Optional: use another AngaraBase instance to query sys.identity)
  1. 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/
  1. Start on new host:
angarabase-server --config angarabase.conf
  1. 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: noop backend 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

Обновление бинарного релиза

Этот сценарий покрывает 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 чек-листа:

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

  1. Open the Grafana UI.
  2. Navigate to Connections → Data sources.
  3. Add Prometheus.
  4. Set the URL to your Prometheus instance (e.g., http://127.0.0.1:9090).
  5. Click Save & test and confirm the connection succeeds.

Step 4: import the AngaraBase dashboard

  1. Go to Dashboards → New → Import.
  2. Upload the bundled AngaraBase overview dashboard JSON (see the download step below).
  3. Select the Prometheus data source added in the previous step.
  4. 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:

PanelKey metric(s)
QPSangarabase_query_exec_total
Query latency p50/p95/p99histogram buckets
Slow query countangarabase_slow_query_total
Active connectionsgauge
TPS / commit latencyangarabase_txn_commit_total
Lock contentionlock wait counters
Buffer pool pressureangarabase_buffer_pool_hit_total, angarabase_buffer_pool_miss_total
BRIN range efficiencyangara_brin_range_efficiency
Mutation policy rejectionsangara_table_no_delete_rejected_*, angara_table_mutation_epoch
WAL lag / fsync latencyWAL counters
IO latency / checkpoint / GC pressureIO counters

If panels are empty, see Troubleshooting below.

Troubleshooting

No data in panels

  • Check http://<prometheus>/targets: the angarabase target must be UP.
  • Ensure ANGARABASE_METRICS_ADDR matches the targets value 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/ready returns 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.

Diagnostics

Goal

Analyze query performance, inspect server state, and triage issues using AngaraBase’s built-in diagnostic tools.

Prerequisites

  • Running angarabase-server (see Quickstart)
  • psql or 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):

VariableDefaultDescription
ANGARABASE_LOG_MIN_DURATION_MS-1 (disabled)Threshold in milliseconds. Set to 0 to log all queries.
ANGARABASE_LOG_QUERY_TEXT0Include 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

  • EXPLAIN variants return plan text (or JSON) without errors.
  • angara_stat_activity shows at least the current session.
  • angara_stat_statements accumulates entries after queries are executed.
  • sys.health returns {"status":"ready"} on a healthy instance.

Troubleshooting

SymptomAction
EXPLAIN ANALYZE modifies dataThis should not happen — DML runs in a dry-run transaction. If data changes persist, file a bug via Support.
angara_stat_statements is emptyEnsure queries have been executed since the last reset. Check ANGARABASE_STAT_STATEMENTS_MAX is not 0.
Slow-query log has no entriesVerify ANGARABASE_LOG_MIN_DURATION_MS is set to a non-negative value and queries actually exceed the threshold.
sys.health shows not-readyCheck GET /health/ready for the JSON reason. Collect a diagnostics bundle — see Monitoring.

For unresolved issues see Known issues and 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 (env ANGARABASE_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

AngaraBase использует tracing. Есть два уровня наблюдаемости:

  1. Логи сервера — вербозность задаёт RUST_LOG (см. Логирование).
  2. Трассы запросов (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 или filestderr
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-экспортёра — поднимите уровень (см. Логирование).

См. также

USDT / eBPF probes

AngaraBase встраивает USDT-пробы (User Statically-Defined Tracing) — точки инструментации для eBPF-инструментов (bpftrace, bcc, perf).

  • Zero-overhead, пока не подключён трейсер: в бинаре это NOP-инструкции.
  • Без рестарта: трейсер цепляется к работающему процессу.
  • Провайдер — angarabase; пробы компилируются с feature usdt (включён по умолчанию). Сборка --no-default-features их исключает.

Проверка наличия проб

# пробы встроены?
readelf -n ./angarabase-server | grep -A5 stapsdt

# список доступных проб
bpftrace -l 'usdt:./angarabase-server:angarabase:*'

Теги запросов (query_tag)

Каждая проба несёт tagu64-хеш (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_startsession_id u64, query_fingerprint u64, tag u64
query_endsession_id, query_fingerprint, total_us, outcome u8, tag, rows
phase_startsession_id, phase u8, tag
phase_endsession_id, phase u8, duration_us, tag
lock_wait_startsession_id, lock_type u8, tag, resource_id
lock_wait_endsession_id, wait_us, tag
io_startsession_id, op_type u8, bytes u32, tag, table_id u32
io_endsession_id, latency_us, tag
operator_startsession_id, tag, operator_type u8, table_id u32 (только tag≠0)
operator_endsession_id, tag, operator_type u8, rows_out, duration_us (только tag≠0)

Энумы (append-only):

  • phase: 0=parse, 1=plan, 2=execute, 3=commit
  • outcome: 0=Ok, 1=Error, 2=Timeout, 3=Cancelled
  • lock_type: 0=Row, 1=Page, 2=Table, 3=Transaction
  • op_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 (см. выше) или несовместимое ядро.

См. также

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 стабилизировались:

Инцидентный 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;
  • сетевые ошибки -> вероятен Net path.

Шаг 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

SymptomAction
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_* считать вспомогательными

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=1 but 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_suites is sensitive (policy: all tls.* knobs are security-sensitive per security-governance.md)
  • Private key (tls.key_path) is never exposed in sys.settings or 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:

Проверка релизных артефактов

Цель

Подтвердить три свойства перед установкой:

  1. артефакт подлинный (GPG signature);
  2. артефакт не поврежден (SHA256);
  3. артефакт соответствует ожидаемой версии.

Пошаговый 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 совпали:

Operations Overview

Канонический operations-корпус AngaraBase для DBA и SRE. Здесь собраны runbooks, baselines и контрольные списки, поддерживаемые в синхронизации с кодом и release trains.

Если вы только начинаете — начните с пользовательских руководств в Эксплуатация (How-to): они короче и подходят как entry point. Этот раздел — operator-level deep-dives.

Как ориентироваться

ЗадачаКуда идти
Поднять инстанс с нуляУстановкаConfiguration
Запустить контейнер / k8s minimalContainer deployment quickstart
Перевести в productionOperational policies baselineHardeningSecurity operations baseline
Настроить мониторинг и алертыObservability metrics checklistParallel runtime observability
Расследовать проблему в productionTroubleshooting guideDiagnostics bundle runbookError debug runbook
Читать планы запросовHow to read query plansPerformance tuning guide
Оптимизировать производительностьPerformance tuning guideHow to read query plansParallel runtime observability
Резервная копия / восстановлениеBackup and restore (operator-level)Disaster recovery playbook
Обновить версиюUpgrade and migration
Подключить незнакомый клиент / ORMClient compatibility baseline
Подготовить voucher для bug-репортаDiagnostics bundle runbookSupport

Каноничные operations-страницы

Lifecycle

Reliability

Performance

Observability

Security

Reference

Troubleshooting

Validation

Ссылки

  • 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 baselineOperator-уровень known issues
Operational policies baselineProduction policy baseline

Validation

ДокументКогда использовать
Testing and validation baselineAcceptance-проверки перед production
Golden dataset managementУправление эталонными датасетами
CI reproducibility contractКонтракт воспроизводимости артефактов

По симптому (быстрая навигация)

СимптомКуда смотреть
Сервер не стартуетTroubleshootingConfigurationCrash recovery
Запросы стали медленнееPerformance tuningDiagnosticsDiagnostics bundle
Ошибка 0A000 feature_not_supportedSQL compatibilityKnown issues
Растёт занятый размер на дискеMVCC and GC operator minimumDiagnostics
Растёт RSS / OOMjemalloc profilingConfiguration
Backup или restore завершился ошибкойBackup and restoreDisaster recovery
Аутентификация / RLS / audit ведут себя неожиданноSecurity operationsSecurity model
Проблема с клиентом / ORMClient compatibilitySQL compatibility
Подозрение на data corruptionVerify release artifactsDisaster recovery

Если runbook не помог

Соберите diagnostics bundle и обратитесь по Support flow.

Дальше

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 правилам

AlertSeverityRunbook
AngarabaseDowncriticalangarabase-down.md
HighP99Latencywarninghigh-p99-latency.md
HighSlowQueryRatiowarninghigh-slow-query-ratio.md
BufferPoolPressurewarningbuffer-pool-pressure.md
WALFsyncSlowwarningwal-fsync-slow.md
DeadlockSpikecriticaldeadlock-spike.md
LongTransactionwarninglong-transaction.md
GCBloatHighwarninggc-bloat-high.md
ReplicationLagwarningreplication-lag.md
IndexRoutingLegacyFallbackwarningindex-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 страница содержит:

  1. Что означает (обязательно) — короткое объяснение alert семантики + PromQL ссылка.
  2. Severity — critical / warning / info.
  3. Initial response (≤ 5 минут) — что сделать прямо сейчас.
  4. Diagnostics — конкретные команды (curl, psql, iostat, …).
  5. Mitigation — таблица “симптом → действие”.
  6. Escalation — когда и как эскалировать.
  7. Связанные — ссылки на смежные runbooks и reference docs.

Связанные

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
    
  • Lease: см. crash-recovery.md если сервер упал из-за ResourceBusy (PID файл / lease).

  • Network: ss -s, iptables -L -n, проверить firewall между Prometheus и instance.

Mitigation

СценарийДействие
Процесс упалsystemctl restart angarabase-server + собрать crash dump
Lease stuckANGARABASE_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

  1. Открыть Grafana dashboard AngaraBase Overview v2 → row “Query Performance”.
  2. Сравнить с P50/P95 — если все три выросли вместе, это глобальная проблема (CPU/IO/lock); если только P99 — tail latency (GC, fsync stall, single slow query).
  3. Проверить slow_query_total rate — растёт ли число 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 / _err counter’ы (Design Gap DG-1, перенесено в 0.6.6.0). Slow-query ratio — best-effort proxy для client-perceived degradation. Истинный HighErrorRate появится после split’а counter’ов.

Severity

warning. Сигнал деградации, не отказ.

Initial response

  1. Открыть Grafana Overview v2 → row “Query Performance” → panel “Slow queries / Total queries ratio”.
  2. Drill-down в Query Store dashboard → top-N slow queries.
  3. Проверить корреляцию с 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 + эскалация.

Связанные

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

  1. Grafana Overview v2 → row “Buffer Pool & Memory”.
  2. Сравнить pages_loaded rate с pages_evicted rate — есть ли churn.
  3. Проверить 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.

Связанные

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

  1. Grafana Overview v2 → row “WAL & Durability”.
  2. Проверить, не выросла ли WAL throughput rate (bytes/s) — переполнение write buffer.
  3. 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 значениеХарактеристикаПрименение
RelaxedrelaxedWAL буферизуется, без fsync per commitDev/bench только
Group commitgroup_commitWAL pump коалесцирует и fsync по батчуProduction (по умолчанию)
Sync at commitsync_at_commit или strictfsync на каждом COMMITБанки, финансы, max durability

Важно: SET [LOCAL] durability = ... и COMMIT WITH DURABILITY = ... зарезервированы для v0.6.5 и возвращают SQLSTATE 0A000 feature_not_supported. Для конфигурации используйте env.

Базовые ожидания по latency

РежимУсловиеОжидание (ориентир)
relaxedfsync=falsesub-ms COMMIT; не для production
group_commitfsync=falseCOMMIT ~0.1–5 ms; батчи сглаживают spikes
group_commitfsync=trueCOMMIT 2–20 ms; доминирует диск
sync_at_commitNVMeCOMMIT 1–5 ms per tx (один fsync)
sync_at_commitHDDCOMMIT 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.

Тюнинг-порядок

  1. Подтверди режим durability (ANGARABASE_TRANSACTION_LOG_DURABILITY) и целевой SLA.
  2. Для sync_at_commit: убедись, что WAL файлы на NVMe / отдельном шпинделе.
  3. Проверь, не ушёл ли workload в burst: сравни tx-rate и batch-size histogram.
  4. Для production сначала стабилизируй диск, затем подбирай group_commit_interval_ms.
  5. Для 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_seconds p99 > 50 ms при sync_at_commit — проверить I/O stall.
  • Если errors_total > 0 в TPC-B-lite smoke — стоп на performance claims до устранения correctness.

Связанные

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

  1. Grafana Overview v2 → row “Locks”.
  2. Проверить, какие таблицы участвуют в spike (см. лог сервера на сообщения deadlock detected: ...).
  3. Сопоставить с 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

  1. Grafana Overview v2 → row “GC / MVCC”.
  2. Найти 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

  1. Grafana Overview v2 → row “GC / MVCC”.
  2. Проверить LongTransaction алерт — обычно root cause там.
  3. Проверить 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

  1. Закрыть длинные транзакции — см. LongTransaction.
  2. Запустить vacuum на горячих таблицах.
  3. Настроить GC — увеличить агрессивность auto-tuning (см. mvcc-gc.md §Knobs).
  4. Полный 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

  1. Grafana Overview v2 → row “Replication”.
  2. На primary: проверить slot status / sender backpressure.
  3. На реплике: проверить 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
Реплика медленнее primaryUpgrade 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’а — это баг, эскалировать.

Связанные

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

  1. Найти повреждённый файл по blob_uri из сообщения об ошибке.
  2. Проверить целостность storage volume (IO errors в dmesg, S.M.A.R.T.).
  3. Если файл повреждён безвозвратно — выполнить restore из backup (disaster-recovery.md).
  4. При повторяющихся CRC ошибках — включить мониторинг angarabase_columnar_pending_deleted_rows для отслеживания DV fragmentation pressure.

Triage fast-path

  1. Проверить версию бинарника и активный конфиг.
  2. Снять базовые метрики (commit_ack_latency, checkpoint, backpressure).
  3. Проверить состояние recovery/txn log.
  4. Применить remediation по соответствующему инциденту.

Расширенные связанные материалы:

Дальше

Disaster Recovery Playbook

Базовый DR playbook на случай, когда штатный recovery path не закрывает инцидент. Каноничный источник: этот runbook в angarabook/src/operations/.

Scope

Покрывает минимальные сценарии:

  • повреждение WAL;
  • потеря data directory;
  • emergency-режимы с осознанным риском.

1) Corrupted WAL

Symptoms

  • ChecksumMismatch или InvalidRecord при старте.

Actions

  1. Если повреждение в tail, ожидать штатный truncate/recovery path.
  2. Если повреждение в середине:
  • приоритетно restore из валидного backup (см. Backup and restore);
  • emergency truncate допустим только как last resort с риском потери транзакций.

2) Lost data directory

Actions

  1. Восстановить data_directory из full backup (процедура — Backup and restore).
  2. Проверить, что WAL содержит непрерывную цепочку после точки backup.
  3. Запустить replay и подтвердить консистентность проверками.

3) Emergency modes (high risk)

  • Игнор/ослабление проверок целостности допустимо только как break-glass.
  • Любой такой запуск требует явного incident evidence и пост-инцидентного восстановления в штатный режим.

4) Prevention baseline

  • Регулярные проверенные backup/restore rehearsal.
  • Atomic snapshots data+txlog при использовании snapshot стратегии.
  • Наличие pinned evidence для последних упражнений 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_size
  • group_commit.max_wait_us
  • checkpoint.interval_ms
  • checkpoint.target_ms
  • checkpoint.dirty_ratio_soft|hard
  • writeback.max_bytes_per_sec
  • txn.max_write_set_pages|bytes
  • buffer_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

Этот 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

Читаем так:

  1. VectorSeqScan читает таблицу public.ux_stats_v2.
  2. VectorFilter применяет условие WHERE.
  3. Project оставляет нужные колонки в результате.
  4. Блок 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.00startup_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 выполняются через векторизованный путь:

  • VectorSeqScan
  • VectorIndexScan
  • VectorFilter
  • VectorProject
  • VectorWindowFunction
  • VectorSetOperation

Векторный путь обрабатывает данные пачками, снижая overhead на строку. Для оператора это обычно хороший признак, особенно на scan/filter/aggregate workload.

Если ожидаемый Vector* исчез:

  1. Проверьте query shape: не добавили ли выражение, которое пока не поддерживается vector executor-ом.
  2. Сравните EXPLAIN (VERBOSE, DIAGNOSTIC) до/после изменения запроса.
  3. Смотрите reason_codes и плановые node types.
  4. Для 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.
NLIndexJoinNested-loop probe по индексу.Малый outer input + селективный index lookup.Большой outer input: может превратиться в много index probes.
AggregateCOUNT, 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.
SetOperationUNION, INTERSECT, EXCEPT.Set queries.Если unexpectedly дорогой из-за dedup/sort.
LateralJoinLATERAL/derived-table dependent path.Коррелированные derived inputs.На больших outer inputs может быть дорогим.
LateMaterializeОтложенная материализация колонок. Читает только необходимые для фильтрации колонки, а остальные дочитывает позже для строк, прошедших фильтр.Высокая селективность фильтра (selectivity < 0.3).Если селективность низкая, двойное чтение может быть дороже обычного.
DmlInsert / DmlUpdate / DmlDeleteSentinel для DML.EXPLAIN DML показывает intent.Для runtime counters используйте EXPLAIN ANALYZE осторожно.
DdlSentinel для 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 там, где ожидали индекс:

  1. Проверьте актуальность статистики (ANALYZE).
  2. Проверьте значение distinct_estimate в sys.column_stats.
  3. Подстройте пороги в 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-а:

  • select
  • write
  • ddl
  • другие классы, если конкретный путь их маркирует.

Оператору это помогает отделить OLTP read path от write/DDL событий.

replan_reason

Почему план был перестроен или почему явной причины нет.

ЗначениеСмыслЧто делать
noneЯвной причины перепланирования нет. Обычно это нормальный путь.Если cache_status=hit, кэш работает.
stats_driftСтатистика изменилась достаточно сильно, старый план мог устареть.Проверить частоту ANALYZE, churn таблицы, стабильность latency.
schema_changedСхема изменилась: DDL, индекс, колонка или другой schema signal.Нормально после миграций; подозрительно при частом DDL в production.
aqp_feedbackRuntime feedback повлиял на оценку/планирование.Проверить AQP metrics и skew workload.
forced_fallbackPlanner/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.
unknownRuntime не передал статус.Не делайте выводов о кэше только по этому полю.

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_memHash 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 Type
  • Startup Cost
  • Total Cost
  • Plan Rows
  • Plans
  • workers_planned
  • workers_launched
  • numa_affinity
  • query_fingerprint
  • plan_fingerprint
  • replan_reason
  • reason_codes
  • cache_status

Для release evidence сравнивайте не весь JSON byte-for-byte, а устойчивые свойства: node class, join type, fingerprints, reason codes и ключевые оценки.

Типовые сценарии чтения

1. Медленный точечный lookup

Симптом:

VectorSeqScan table=public.orders ... rows=1000000

Что проверить:

  1. Есть ли индекс по колонке фильтра.
  2. Видит ли планировщик статистику (sys.column_stats).
  3. Не показывает ли diagnostics stats_default_fallback.
  4. Не слишком ли низкая селективность фильтра.

Желаемый план для точечного 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=...

Что проверить:

  1. Можно ли отфильтровать строки до aggregate.
  2. Есть ли лишние projected columns.
  3. Подходит ли group key под fast path (например, single integer key).
  4. Не слишком ли много групп.
  5. Не требует ли запрос сортировки после aggregate.

5. Parallel planned, но latency высокая

Симптом:

workers_planned=2 workers_launched=0

или workers_launched меньше workers_planned.

Что проверить:

  1. Глобальные лимиты parallel runtime.
  2. CPU saturation.
  3. Очереди pgwire/runtime.
  4. Memory pressure.
  5. 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

Когда пользователь говорит «запрос стал медленным», действуйте так:

  1. Снимите план:

    EXPLAIN (VERBOSE, DIAGNOSTIC)
    <query>;
    
  2. Если безопасно, снимите runtime:

    EXPLAIN ANALYZE
    <query>;
    
  3. Прочитайте дерево снизу вверх.

  4. Найдите самый широкий input (rows резко больше ожидаемого).

  5. Проверьте, используется ли ожидаемый operator class: IndexScan, IndexOnlyScan, HashSemiJoin, Aggregate, Vector*.

  6. Проверьте reason_codes.

  7. Если есть stats_default_fallback, выполните ANALYZE и сравните план.

  8. Сравните query_fingerprint и plan_fingerprint до/после.

  9. Если проблема в parallel path, переходите к Parallel runtime observability runbook.

  10. Если проблема в storage/IO, переходите к Performance tuning guide.

Частые ошибки интерпретации

ОшибкаПочему неверноПравильно
cost=1000 значит 1000 msCost — условная модель 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, если есть.

Дальше

MVCC and GC Operator Minimum

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

Goal

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

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

Metrics to watch

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

Core knobs

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

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

Triage: “GC not keeping up”

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

UndoStore GC (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:

  1. Проверить txn_oldest_snapshot_age_seconds — долгие (зависшие) транзакции блокируют продвижение gc_watermark.
  2. Найти и завершить зависшие транзакции (kill).
  3. Проверить логи сервера на наличие ошибок 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.
  • src/operations/diagnostics-bundle.md
  • src/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.txt
  • on_disk_inspect.json
  • config.redacted.conf, config_redaction.txt
  • metrics.prom (или metrics.prom.error.txt)
  • summary.json
  • ok.txt

Security policy

Секреты в конфиге редактируются: значения ключей по шаблонам password, secret, token, api_key заменяются на "<REDACTED>".

Evidence routing

  • Heavy bundle хранится в artifacts/diagnostics/<stamp>/...
  • В документации фиксируются только компактные pinned summaries/evidence pointers.

Дальше

Security Operations Baseline

Операторский security baseline: security-relevant knobs в едином операционном контракте — безопасные дефолты, fail-closed гейты, точки наблюдаемости (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

  1. Remote bind без allow_insecure должен завершаться отказом старта.
  2. Password auth без TLS должен завершаться отказом старта.
  3. Изменение настроек в рантайме (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_bind
  • ANGARABASE_AUTH_MODE, ANGARABASE_TLS_ENABLE
  • ANGARABASE_TDE_ENABLE, ANGARABASE_TDE_MASTER_KEY_ID
  • ANGARABASE_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.

Дальше

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 не совпадает с compiled PAGE_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

Рекомендуемый общий путь:

  1. Backup старого состояния.
  2. --init в новом формате.
  3. Restore данных.
  4. Пост-проверки startup и recovery.

In-place migration pre-v1 ограничена и должна выполняться только по документированному runbook-пути.

Upgrade rehearsal

Перед production rollout:

  • прогон репетиции обновления на staging;
  • фиксация артефактов в evidence;
  • проверка rollback-плана.

Подробные процедуры:

  • src/operations/testing-validation.md
  • src/operations/backup-restore.md

Дальше

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 версии рекомендуется:

  1. сделать cold backup;
  2. сохранить архив как rollback point;
  3. прогнать 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, env ANGARABASE_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

Правило приоритета:

  1. default
  2. config (angarabase.conf)
  3. environment override

Контракт: default -> config -> env.

Critical env surface (operator minimum)

  • ANGARABASE_TRANSACTION_LOG* (backend/durability/fsync)
  • ANGARABASE_METRICS_ADDR
  • ANGARABASE_TDE_*
  • ANGARABASE_TLS_*
  • ANGARABASE_MAX_DATASET_BYTES
  • ANGARABASE_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 не успевает; уменьши интервал.

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.

Buffer Pool Config (0.6.6.8)

В 0.6.6.8 были добавлены настройки для управления политикой вытеснения страниц и изоляции ресурсов для GC.

  • ANGARABASE_BUFFER_POOL_EVICTION: Выбор алгоритма вытеснения страниц.
    • Default: "2q"
    • Values: "2q", "3q" (включает полную политику 3Q с разделением на A1/Am очереди).
  • 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.

#МетрикаТипНормальный диапазонЧто значит выход за границу
1angarabase_server_connections_activegauge< 80% max_poolConnection leak / отсутствие PgBouncer — проверить angara_stat_activity
2angarabase_txn_rollback_total (rate 1m)counter rate< 5% от commit rateАномальный rollback rate — конфликты MVCC, deadlock или баги приложения
3angarabase_storage_dirty_pages_totalgauge< 10 000 стр.Checkpoint не успевает — снизить write rate или уменьшить checkpoint interval
4angarabase_checkpoint_errors_total (change)counter0Ошибка checkpoint = критичный инцидент; смотреть логи немедленно
5angarabase_transaction_log_flush_lsn vs durable_lsn (delta)gauge< 1 МББольшой gap = WAL durability lag; риск потери данных при crash
6angarabase_query_exec_duration_ms_bucket P99histogram< 100 msP99 деградация — смотреть angara_stat_activity + EXPLAIN
7angarabase_buffer_pool_miss_total (rate)counter rate< 20% hit/missНизкий cache hit ratio — увеличить buffer_pool_size_mb
8angarabase_memory_rss_bytesgauge< soft_limit*0.9Приближение к soft limit — OOM risk; проверить query patterns + GC
9angarabase_qos_rejected_critical_total (rate)counter rate0Любые CRITICAL rejections = production incident candidate
10angarabase_uptime_secondsgaugeмонотонно растётЗначение < 60 после паузы = unexpected restart / crash

Полный справочник метрик

Соединения и сессии

МетрикаТипЧто измеряетНормаВыход за границу
angarabase_server_connections_activegaugeАктивные клиентские соединения< max_pool * 0.8Проверить pool config, connection leaks
angarabase_connections_accepted_totalcounterВсего соединений с момента стартамонотонноВнезапный всплеск rate — DDoS или reconnect storm
angarabase_pgwire_active_tasksgaugeАктивные spawn_blocking задачи pgwire≤ max_blocking_threadsSaturation blocking runtime path
angarabase_session_claims_set_totalcounterУстановки session claims (app.*)Используется для audit trail

Диагностика соединений:

SELECT pid, state, consumer_id, wait_event FROM angara_stat_activity;

Транзакции и MVCC

МетрикаТипЧто измеряетНормаВыход за границу
angarabase_txn_begin_totalcounterВсего BEGINBaseline для throughput
angarabase_txn_commit_totalcounterВсего COMMITrate(1m) = TPS
angarabase_txn_rollback_totalcounterВсего ROLLBACK< 5% от commitКонфликты, ошибки приложения
angarabase_txn_active_countgaugeТранзакций в полёте< 100 (OLTP)Долгие txn — проверить txn_oldest_snapshot_age_seconds
angarabase_txn_commit_conflicts_totalcounterКонфликты MVCCблизко к 0Высокий rate = конкурирующие writes на одни строки
angarabase_txn_oldest_snapshot_age_secondsgaugeВозраст старейшего snapshot< 60sДолгий snapshot блокирует GC → GC bloat
angarabase_mvcc_history_versions_totalgaugeВерсий в MVCC storeрастёт медленноБыстрый рост = GC не успевает (см. MVCC GC runbook)
angarabase_txn_commit_epoch_currentgaugeТекущая 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_lsngaugeLSN последней flushмонотонноОстановка роста = WAL writer hung
angarabase_transaction_log_durable_lsngaugeLSN последнего fsync (глобально)≤ flush_lsngap > 1 МБ = durability lag
angarabase_wal_durable_lsn{db="<name>"}gaugePer-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_idgaugeID последнего checkpointмонотонно
angarabase_transaction_log_checkpoint_end_valid_totalcounterУспешных checkpoint endsмонотонно
angarabase_transaction_log_checkpoint_end_invalid_totalcounterНевалидных checkpoint ends0> 0 = повреждение WAL
angarabase_wal_sync_wait_totalcounterWAL sync waits (strict mode)rate растёт = I/O latency
angarabase_wal_group_commit_wait_totalcounterWAL group commit waitsrate растёт = group commit backlog
angarabase_transaction_log_bytes_appended_totalcounterБайт записано в WALWAL write throughput
angarabase_wal_redo_heap_rows_reconstructed_totalcounterСтроки, восстановленные из WAL redo в HeapStore0 (steady)> 0 только при recovery после crash
angarabase_wal_redo_heap_pages_written_totalcounterСтраницы HeapStore, записанные WAL redo pass0 (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_totalgaugeГрязные страницы в памяти< 10 000Checkpoint lag; снизить write rate или checkpoint_interval
angarabase_storage_cached_pages_totalgaugeЗакэшированные страницырастёт до bp sizeВнезапное падение = eviction storm
angarabase_buffer_pool_hit_totalcounterCache hitshit rate = hits / (hits + misses)
angarabase_buffer_pool_miss_totalcounterCache missesmiss rate > 20% = нужен больший buffer pool
angarabase_buffer_pool_warmup_pages_totalcounterСтраниц загружено при warmupПосле restart
angarabase_storage_flush_ok_totalcounterУспешных flushмонотонно
angarabase_storage_backpressure_events_totalcounterBackpressure events0> 0 = writer faster than disk
angarabase_storage_backpressure_commit_rejected_totalcounterCommit rejected by backpressure0Производительность I/O недостаточна
angarabase_storage_flush_bytes_totalcounterБайт сброшено на диск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_totalcounterУспешных чекпоинтов> 0 за 5 мин= 0 за 10 мин = checkpoint stopped
angarabase_checkpoint_errors_totalcounterОшибок checkpoint0Немедленно смотреть логи
angarabase_checkpoint_dirty_pagesgaugeГрязных страниц на момент checkpoint< 5 000Высокое значение = checkpoint не успевает
angarabase_checkpoint_duration_ms_sumcounterСуммарное время checkpoint (мс)avg = sum/count
angarabase_checkpoint_aborted_totalcounterПрерванных checkpoint0> 0 = отмены; проверить причину
angarabase_checkpoint_per_db_timeout_totalcounterPer-DB checkpoint timeouts0timeout = диск слишком медленный
angarabase_wal_forced_checkpoints_totalcounterПринудительных checkpoint по backpressure0> 0 = write pressure критична
angarabase_overlay_flush_on_checkpoint_slots_totalcounterOverlay-слоты, сброшенные в heap при checkpointИнтенсивность материализации overlay
angarabase_overlay_flush_on_checkpoint_tables_totalcounterТаблицы, затронутые 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"}counterSELECT queries OKQPS baseline
angarabase_query_exec_total{outcome="ok",class="write"}counterWrite queries OKWrite TPS
angarabase_query_exec_total{outcome="err",class="select"}counterSELECT errorsблизко к 0rate растёт = баги или перегрузка
angarabase_query_exec_duration_ms_buckethistogramLatency distributionP99 < 100msP99 > 500ms = деградация
angarabase_slow_query_totalcounterSlow queries (> threshold)0> 0 = нужен EXPLAIN slow queries
angarabase_sql_routing_not_supported_totalcounterUnsupported SQL routes0> 0 = приложение использует неподдерживаемый SQL
angarabase_legacy_fallback_triggered_totalcounterLegacy path fallbacks0> 0 = unsupported query план
angarabase_simd_agg_fallback_totalcounterFallback SIMD агрегации на скалярный путь0> 0 = отсутствие поддержки AVX2/NEON или несовместимость типов
angarabase_adaptive_probe_swap_totalcounterКоличество адаптивных переключений сторон 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_bytesgaugeRSS процесса (байт)< soft_limit * 0.9OOM risk; проверить query patterns
angarabase_memory_soft_limit_exceeded_totalcounterПревышений soft_limit_mb0> 0 = память под давлением
angarabase_tx_overlay_dataset_bytes_totalgaugeIn-memory tx overlay size< 512 МББольшие txn держат много данных в памяти

QoS Scheduler

МетрикаТипЧто измеряетНормаВыход за границу
angarabase_qos_rejected_critical_totalcounterОтказов CRITICAL queue0Incident candidate — немедленный triage
angarabase_qos_rejected_interactive_totalcounterОтказов INTERACTIVE queue0User-facing degradation
angarabase_qos_rejected_background_totalcounterОтказов BACKGROUND queueСнизить background concurrency
angarabase_qos_blocking_inflightgaugeБлокирующих задач< max_blockingscheduler saturation
angarabase_spawn_blocking_activegaugeАктивных 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_bytesgaugeResident Set Size процесса сервера в байтах. Обновляется каждые 5с.
angarabase_memory_soft_limit_exceeded_totalcounterКоличество пересечений порога soft_limit_mb (edge-trigger).
angarabase_buffer_pool_warmup_evictions_during_warmup_totalcounterКоличество вытеснений страниц из buffer pool во время прогрева (warmup cap enforcement).
angarabase_buffer_pool_warmup_completed_pagescounterКоличество страниц, загруженных при прогреве.
angarabase_buffer_pool_warmup_aborted_at_cap_totalcounterWarmup прерван из-за превышения 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_totalcounterОбщее число выполненных чекпоинтов. > 0 после 5 мин uptime подтверждает работу auto-checkpoint.

Visibility Map and Index-Only Scan (0.6.4.3)

МетрикаТипСмысл
angarabase_visibility_map_all_visible_fractiongaugeДоля all-visible страниц (сигнал для планировщика).
angarabase_index_only_scan_hits_totalcounterУспешные Index-Only Scan (без обращения к Heap).
angarabase_index_only_scan_heap_fetches_totalcounterFallback на Heap при Index-Only Scan (бит VM=0).
angarabase_visibility_map_rebuild_pages_remaininggaugeОстаток страниц для фонового восстановления VM.
angarabase_visibility_map_corrupt_totalcounterОбнаруженные повреждения 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_totalcounterЧисло commit-wait событий по пути IO::WalSync (строгая durability).
angarabase_wal_group_commit_wait_totalcounterЧисло 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_totalcounterFallback stream-плана на legacy executor.
angarabase_vector_fallback_totalcounterFallback vector-пути на row-путь (неподдерживаемый план или ошибка типа).
angarabase_vector_columnar_native_totalcounterУспешные активации нативного векторного пути для columnar таблиц.
angarabase_columnar_batched_scan_batches_totalcounterВсего обработанных колоночных батчей в нативном пути.
angarabase_columnar_segments_pruned_totalcounterКоличество сегментов, отсеченных по метаданным (zone-map pruning).
angarabase_parallel_agg_totalcounterКоличество запусков параллельного агрегатора.
angarabase_vector_memory_budget_exceeded_totalcounterОтказ выделения бюджета вектора (SQLSTATE 53100).
angarabase_columnar_manifest_init_failed_totalcounterОшибка init SegmentManifest при CREATE TABLE USING COLUMNAR.
angarabase_vector_numeric_float_backed_totalcounterLossy-mapping: numeric(p,s>0) → Float64 в vector-пути (0.6.7.15). Ненулевое = float-потеря точности. Подробнее: vector-numeric-columnar-agg-metrics.md.
angarabase_vector_columnar_grouped_agg_totalcounterGROUP 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_rowsgauge (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 index
  • angarabase_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_totalcounterВсего задач поставлено в QoS CRITICAL queue.
angarabase_qos_queued_interactive_totalcounterВсего задач поставлено в QoS INTERACTIVE queue.
angarabase_qos_queued_background_totalcounterВсего задач поставлено в QoS BACKGROUND queue.
angarabase_qos_rejected_critical_totalcounterОтказы CRITICAL queue с SQLSTATE 53600.
angarabase_qos_rejected_interactive_totalcounterОтказы INTERACTIVE queue с SQLSTATE 53600.
angarabase_qos_rejected_background_totalcounterОтказы BACKGROUND queue с SQLSTATE 53600.
angarabase_qos_blocking_inflightgaugeТекущие blocking tasks across QoS shards.
angarabase_spawn_blocking_maxgaugeЛимит spawn_blocking threads из настройки max_blocking_threads; 0 до startup init.
angarabase_spawn_blocking_activegaugeАктивные 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_blocking wait 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.rs
  • prometheus_export_contains_must_have_metrics_names

Дальше

Materialized View Metrics

MetricTypeDescription
angarabase_mv_refresh_totalcounterTotal number of materialized view refreshes. Labels: {mode, status}.
angarabase_mv_refresh_duration_mshistogramDuration of materialized view refresh operations. Labels: {mode}.
angarabase_mv_auto_refresh_scheduled_totalcounterNumber of automatically triggered (scheduled) refreshes.
angarabase_mv_auto_refresh_lag_secondsgaugeLag between the scheduled refresh time and actual refresh time. Labels: {mv}.
angarabase_mv_incremental_refresh_rows_applied_totalcounterNumber of rows applied during incremental (async) refreshes. Labels: {mv_name}.

Online DDL Metrics

MetricTypeDescription
angarabase_online_ddl_operations_totalcounterTotal number of Online DDL operations initiated. Labels: {op, status}.
angarabase_online_ddl_copy_rows_totalcounterTotal number of rows copied during the ghost-table phase. Labels: {table}.
angarabase_online_ddl_cutover_duration_mshistogramDuration of the final cutover phase (blocking).

Метрики статистики (0.6.7.2)

МетрикаТипОписание
angarabase_stats_inline_updates_totalcounterЧисло inline-обновлений row_count_live на COMMIT. Ненулевое при активных DML транзакциях.
angarabase_stats_async_recalc_activegauge1 когда фоновый воркер активно выполняет гистограммный пересчёт, 0 — простой.
angarabase_stats_drift_ratiogaugeКоэффициент дрейфа статистики (0–1000, масштабировано). Растёт при большом числе DML без ANALYZE.
angarabase_optimizer_drift_fallback_totalcounterЧисло планов где 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_totalcounterLegacy-сигнал старого lossy float-backed numeric-пути. С 0.6.7.16 всегда 0 (numeric теперь exact Decimal, см. ниже).
angarabase_vector_columnar_grouped_agg_totalcounterКоличество раз, когда 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 - bmax(scale_a, scale_b)
a * bscale_a + scale_b
a / bmax(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_supportedp>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_totallegacy 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_total
  • angarabase_columnar_compaction_duration_ms
  • angarabase_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.

Связанные

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:

  1. Текущий wait сессииangara_stat_activity.wait_event_type и angara_stat_activity.wait_event.
  2. Агрегированные метрики Prometheus — counters, gauges и histograms по каждому wait event.

События

WaitEvent — стабильный public API. Добавление variant является non-breaking: dashboards увидят новый event=... label после upgrade. Удаление, renumbering или изменение as_str() значения считается breaking change.

VariantLabelWait typeКогда срабатывает
RowLockrow_lockLockОжидание tuple-level lock.
PageLockpage_lockLockОжидание page-level latch.
TableLocktable_lockLockОжидание relation-level lock для DDL/lock manager.
TransactionLocktransaction_lockLockОжидание commit/finish другой транзакции.
PredicateLockAcquirepredicate_lock_acquireLockОжидание захвата predicate lock для SSI foundation.
PredicateConflictCheckpredicate_conflict_checkLockОжидание проверки predicate conflict graph.
PageReadpage_readIOЧтение heap/index page при cache miss.
PageWritepage_writeIOWrite-back страницы при checkpoint или eviction.
WalFlushwal_flushIOWAL flush / fsync path.
FsyncfsyncIOПрочие fsync пути: catalog, FPI и смежные операции.
WalSyncwal_syncIOStrict WAL sync wait в durability path.
WalGroupCommitwal_group_commitIOОжидание group commit batch.
ColumnarCompactioncolumnar_compactionIOBackground compactor ждёт disk I/O или manifest append mutex в compact_l0_to_l1().
ClientReadclient_readNetЧтение из client socket.
ClientWriteclient_writeNetЗапись в client socket.
ReplicaReadreplica_readNetЧтение из replica connection.
ReplicaWritereplica_writeNetЗапись в replica connection.
NetReadnet_readNetGeneric network read.
NetWritenet_writeNetGeneric network write.
CpuRuncpu_runCPUСессия исполняется на CPU, это не блокировка.
PageDecompressionpage_decompressionCPUCPU time на decompression страницы при buffer-pool miss.
PageCompressionpage_compressionCPUCPU time на compression dirty page перед flush.
AdmissionQueueadmission_queueSchedulerОжидание admission control queue.
IoSchedulerQueueio_scheduler_queueSchedulerОжидание I/O scheduler queue.
MemoryGrantQueuememory_grant_queueSchedulerОжидание memory grant.
BufferPoolEvictionbuffer_pool_evictionSchedulerСессия ждёт свободный или evictable buffer-pool slot.
BackpressureThrottlebackpressure_throttleSchedulerUnified backpressure coordinator throttles caller.
DiskRestartHarnessdisk_restart_harnessSchedulerTest harness ждёт re-hydration on-disk state при disk-restart тесте.
QosQueueqos_queueSchedulerAsync task стоит в per-shard DRR queue QoS scheduler до dispatch.
QosBlockingqos_blockingSchedulerBlocking 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 имеет ordinal 28;
  • QosBlocking имеет ordinal 29.

Массив 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_totalcounterСколько раз код входил в ожидание этого типа.
angarabase_wait_events_activegaugeСколько ожиданий этого типа активно прямо сейчас.
angarabase_wait_event_duration_secondshistogramРаспределение длительности ожидания.

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:

RowLock имеет высокие duration:

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:

  1. anchor the public Article #5 narrative (no more “future-only” advisors), and
  2. 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):

KnobDefaultNotes
initial_batch_size64 pagesResets to this on restart (no persistence)
min_batch_size8 pagesHard floor
max_batch_size1024 pagesHard ceiling
iops_threshold5 000 IOPSAbove → multiplicative-decrease
decrease_factor0.5Clamped into (0.0, 1.0)
increase_step8 pagesAdditive-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_lsn to preserve the completion invariant. Wiring the recommendation into the flush path is tracked in DEBT_REGISTER as 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):

  1. read process_rss from /proc/self/statm (pages * sysconf(_SC_PAGESIZE)),
  2. compute ratio = process_rss / configured_limit,
  3. publish angarabase_memory_pressure_ratio gauge,
  4. emit a WARN log line if ratio >= warn_threshold (default 0.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 recent process_rss / limit_bytes ratio. Hard-clamped to 8.0 to bound the impact of bogus RSS reads.
# 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

SymptomWhat to checkAction
io_advisor_current_batch_size stuck at min_batch_sizerate(io_advisor_decisions_total{action="throttle"}[5m]) consistently > 0Storage IOPS budget is the bottleneck. Either provision more IOPS or raise iops_threshold after measuring sustained capacity.
memory_pressure_ratio > 0.9 for > 5mRSS growth pattern; per-subsystem memory metricsConsider 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/recoverWorkload is stable around the thresholdNo 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 new action= label values is a non-breaking change.
  • The Rust API (IoAdvisor::tick, MemoryAdvisor::sample, MemoryAdvisor::is_under_pressure) is internal (pub for 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:

  1. The buffer_pool.uncommitted_pages_ratio_hard threshold (write transactions blocked until the writeback worker drains the uncommitted-pages set).
  2. The high-priority I/O queue depth (low-priority prefetch dropped when OLTP demand reads saturate the I/O scheduler).
  3. 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:

DecisionMeaningTypical caller reaction
passSource reports no pressure; the request may proceed without delay.Continue.
throttleSource reports elevated pressure; the caller should slow down.Block on a WaitEventGuard for BackpressureThrottle.
rejectSource 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 labelSignalTunable knob
uncommitted_pagesFraction of buffer-pool frames carrying uncommitted page-image deltas.buffer_pool.uncommitted_pages_ratio_hard (default 0.30).
wal_queueHigh-priority I/O queue depth (OLTP demand reads above the saturation watermark).(internal, default threshold 4)
buffer_poolBuffer-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_hard knob was previously named uncommitted_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 with exit 78 (EX_CONFIG) and an operator-facing message naming the renamed key. Unknown keys (typos, future-feature backports) emit a structured tracing::warn!(target = "config", section, key) and increment the counter angarabase_config_unknown_keys_total — recommended alert: > 0 after 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).

MetricTypeLabelsMeaning
angarabase_backpressure_throttle_decisions_totalcountersource, decisionPer (source × decision) counter incremented on every coordinator evaluation.
angarabase_backpressure_active_sourcesgaugeNumber 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

SymptomFirst checkNext step
angarabase_backpressure_active_sources >= 1 for >30 sWhich source label dominates the decision counters?Follow per-source playbook below.
source="uncommitted_pages",decision="throttle" rate climbingangarabase_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 climbingangarabase_io_advisor_current_batch_size shrinking? (correlated)Investigate disk saturation; throttle prefetch / background warmup.
source="buffer_pool",decision="reject" non-zeroangarabase_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

SurfaceTypeSource
angarabase:vector_batch_startUSDT probecrates/angarabase/src/observability/probes.rs
angarabase:vector_batch_endUSDT probecrates/angarabase/src/observability/probes.rs
angarabase:vector_fallbackUSDT probecrates/angarabase/src/observability/probes.rs
angarabase_vector_selection_ratioPrometheus histogramcrates/angarabase/src/metrics/core.rs
angarabase_vector_fallback_totalPrometheus counter (existing)crates/angarabase/src/metrics/core.rs
angarabase_vector_rows_produced_totalPrometheus 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_kindProbeVectorOperatorKind discriminant. 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.
  • sourceProbeVectorBatchSource discriminant. 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_kindProbeOperator discriminant (best-effort tag for the plan node that tripped the fallback; e.g. HashProbe=4, Aggregate=7).
  • reasonProbeVectorFallbackReason discriminant. Stable values: UnsupportedPlan=0, TypeError=1, NonEquiJoin=2, BudgetExceeded=3, FeatureDisabled=4.

Wire contract notice. S17 finalises the vector_fallback argument 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 the ProbeOperator × ProbeVectorFallbackReason mapping.

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

ObservationLikely diagnosisRecommended action
p50 ≥ 0.9 consistentlyFilter is essentially a no-op; predicate could be pushed down or removed entirelyReview query plan: candidate for filter pushdown to scan / index level; rewrite query
p95 ≤ 0.05 and high vector_batch_start rateIndex missing — Filter is throwing away ≥ 95 % of every batchRun ANALYZE; add an index on the predicate columns; verify with EXPLAIN
p99 = 1.0 only on a small set of queriesSelective predicate fires occasionally on a hot tableAcceptable; consider partial index if the predicate is stable
vector_fallback rate spikeA new query shape is tripping the row-path fallbackFilter 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

ArtifactRole
0.6.3.10 §S17Sprint contract (this page is the operator-facing rendering)
crates/angarabase/src/observability/probes.rsUSDT macro definitions + enum stability tests
crates/angarabase/src/metrics/core.rs::VectorSelectionRatioHistogramHistogram storage + observe() API
crates/angarabase/src/metrics/render.rs::render_vector_selection_ratioPrometheus exposition
crates/angarabase/src/query/vector.rs::VectorFilterV0::next_batchSingle 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_bytes
  • angarabase_jemalloc_resident_bytes
  • angarabase_jemalloc_active_bytes
  • angarabase_jemalloc_mapped_bytes
  • angarabase_jemalloc_fragmentation_ratio

Практическая интерпретация:

  • ~1.0: низкая фрагментация;
  • >1.5: риск фрагментации;
  • >2.0: требуется разбор memory path.

Heap profiling workflow

  1. Запуск с MALLOC_CONF=prof:true,....
  2. Сигнал SIGUSR1 для forced dump.
  3. Анализ jeprof (text/pdf/diff).

Leak-check for long-lived runs

Golden DB flow:

  • длительная нагрузка

Сравниваются baseline/after по allocated/resident/mapped и fragmentation.

  • 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

  1. Сверить bench-метрики и серверные метрики в одном временном окне.
  2. Проверить QPS, p95/p99, queue depth, lock waits, error-rate.
  3. Классифицировать проблему: 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_end
  • parallel_worker_cancel, parallel_budget_exceeded
  • Prometheus minimum:
  • angarabase_storage_io_read_duration_ms_*
  • angarabase_storage_io_write_duration_ms_*
  • angarabase_pgwire_pool_queue_depth
  • angarabase_lock_wait_duration_ms_*
  • angarabase_slow_query_total

Incident playbook

  1. Снять baseline и regression run на одном профиле.
  2. Собрать EXPLAIN ANALYZE для медленных запросов.
  3. Проверить, что используется ожидаемый parallel path: workers_planned, workers_launched, Vector* operators и reason_codes.
  4. Сопоставить dispatch/completion с tail latency.
  5. Проверить memory guardrails и деградацию вместо hard-fail.
  6. Зафиксировать short report: impact, suspect component, next action.

Дальше

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_addr
  • wal_retention_segments

Standby:

  • [replication].role = "standby"
  • primary_addr
  • slot_name
  • wal_path

Operations flow

  1. Запуск primary.
  2. Запуск standby и проверка lag-метрик.
  3. Мониторинг 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_standby
  • angara_replication_lag_bytes
  • angara_replication_lag_ms
  • angara_replication_reconnects_total
  • angara_promote_total
  • angara_promote_duration_ms_last

Typical incidents

  • Standby не подключается: адрес/порт/firewall/reconnects.
  • WAL segment gone: нужен base backup и restart standby.
  • Promote timeout: проверить сеть и WAL write path на primary.

Дальше

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_id is 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 / DriverVersionStatusNotes
psqlany✅ Supportedbaseline
psycopg33.3.4✅ SupportedFixed 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 + psycopg35.x✅ SupportedBasic 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✅ SupportedFixed 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).
sqlx0.8.6✅ SupportedFixed in v0.6.5.3: ParameterDescription in Describe(S)
tokio-postgres (simple query)0.7.17✅ SupportedSimple query protocol
tokio-postgres (extended query)0.7.17✅ SupportedFixed 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.json
  • iter_<N>/summary.json
  • iter_<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 типов параметров вместо нулей.

Быстрый путь:

  1. найти failing test в summary;
  2. открыть соответствующий log;
  3. локально воспроизвести точным 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 корректно вычисляет стоимость для низкокардинальных колонок.

Как это работает:

  1. Планировщик вычисляет селективность фильтра на основе distinct_estimate.
  2. Если селективность превышает порог [execution].index_cardinality_threshold (по умолчанию 0.15), планировщик предпочитает SeqScan для соответствующего гейта («low cardinality» в EXPLAIN; см. также порог index_scan_selectivity_threshold для причины «low selectivity»).
  3. В 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 ANALYZE are now persisted to disk (sys_catalog snapshot protocol v4). Statistics survive server restarts. To force a fresh collection, run ANALYZE <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 knobDefaultОписание
ANGARABASE_STATS_DRIFT_MAX_AGE_MS30000Порог возраста снапшота (мс) при котором 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.

ValueBehaviour
'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

SituationSQLSTATE
CREATE SUBSCRIPTION of an existing name42710 (duplicate_object)
Poll/ack/drop of a non-existent subscription42704 (undefined_object)
Invalid subscription name42602 (invalid_name)
Malformed statement42601 (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::CheckpointWorker and exposed via the CheckpointEngineOps trait. The server-side entry point is a thin wrapper. Legacy behaviour is preserved via run_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_totalcounterЧисло overlay-слотов, материализованных в heap.
angarabase_overlay_flush_on_checkpoint_tables_totalcounterЧисло таблиц, для которых выполнен 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-cliCLI для администрирования (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

Ключевые архитектурные решения

ОбластьРешениеПочему
MVCCUNDO-log (история — отдельный append-only log; heap содержит только текущие версии)Меньше bloat, нет тяжёлого VACUUM, детерминированный GC
StoragePluggable: row-store baseline + AngaraMemory; AngaraColumn в roadmapHTAP-направление, разные tier’ы для разных нагрузок
RecoveryWAL-first, идемпотентный replay, fail-closed при отсутствии WAL целостностиКорректность важнее latency
OptimizerCost-based AngaraPlan + LEO feedback loop, robust planningУстойчивость к ошибкам оценок
ExecutionVolcano streaming (AngaraFlow) + vector path (AngaraVector)Разделение по плановым формам, явное управление через EXPLAIN
CatalogPersisted SysCatalog, DDL переживает restartПредсказуемость для production
Security6-слойная модель: TLS/Auth → RBAC → RLS → Break-glass → Audit chain → TDEDefence-in-depth, fail-closed
BackupPer-database, cold + online/PITR baselineMulti-tenant изоляция
DistributionSingle-node engine; distributed SQL — горизонт major-ветокConcentration on correctness first

Границы и инварианты

  • angarabased (адаптер) не содержит SQL-логики — только pgwire framing, session ctx, маршрутизация в core.
  • angarabase core не знает о 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 на чтении/восстановлении.

Дополнительные материалы

Table Partitioning

AngaraBase поддерживает декларативное партицирование: RANGE и LIST стратегии с DEFAULT catch-all.

Поддерживаемые стратегии

СтратегияСинтаксисКогда использовать
RANGEPARTITION BY RANGE (col)Временны́е ряды, диапазоны ID
LISTPARTITION BY LIST (col)Категориальные значения (регион, тип)
DEFAULTPARTITION OF parent DEFAULTCatch-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_totalINSERT без matching partition (→ 23514)
angarabase_partition_route_default_totalINSERT в DEFAULT partition
angarabase_partition_pruned_branches_totalChildren пропущено при 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 supportedON 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:

  1. Table Creation: When a CREATE TABLE ... PRIMARY KEY statement is executed, the DDL executor allocates a unique index_table_id using the storage engine.
  2. Catalog Persistence: The Primary Key definition is saved in the SysCatalog with its assigned index_table_id. This ensures that the mapping between the table and its index is persistent.
  3. Checkpoint Integration: The Checkpoint worker periodically calls flush_all_indexes(). This operation forces all dirty index pages from memory to disk.
  4. 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.
  5. 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 missing index_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:

  1. 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.
  2. 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 INDEX succeeds on volatile InMemory tables.
  • The index definition is visible in the catalog while the table exists.
  • index_table_id is 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_checkpoint record is written to the WAL.
  • Failure: If flush_all_indexes() returns false (indicating a flush error), the checkpoint is aborted. The end_checkpoint record 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:

MetricTypeDescription
angarabase_pkey_backfill_in_progressGauge1 while startup PK backfill is running
angarabase_pkey_backfill_ok_totalCounterPK indexes successfully backfilled with TableId
angarabase_pkey_backfill_fail_totalCounterPK backfill failures (allocation or persist error)
angarabase_checkpoint_index_flush_errors_totalCounterCheckpoint aborted due to index flush failure
angarabase_index_pkey_no_table_id_totalGaugeLegacy PK indexes found at startup (before backfill)
angarabase_index_restore_empty_totalCounterIndexes that restored empty after restart (Alert if > 0)
angarabase_wal_lsn_drift_resets_totalCounterWAL VLF LSN drift resets after crash (Alert if > 0)
angarabase_index_stale_tuple_fallbacks_totalCounterUPDATE 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:

  1. 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).
  2. Checkpoint Failures: Verify if angarabase_checkpoint_index_flush_errors_total is incrementing. A failure to flush indexes prevents the checkpoint from completing. Check disk space and permissions.
  3. Logs: Inspect system logs for WAL replay errors or messages indicating that index pages could not be restored.

“Checkpoint loop не завершается”

If the checkpoint process seems stuck or keeps restarting:

  1. Flush Errors: Check the angarabase_checkpoint_index_flush_errors_total metric.
  2. Worker Logs: Look for checkpoint_worker: flush_all_indexes failed in 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:

  1. 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.
  2. Check the logs for append_commit FAILED or WAL VLF LSN drift messages. 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:

  1. This means UPDATE operations are finding index entries that point to non-existent or stale tuples, forcing a slow sequential scan fallback.
  2. 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.indexes and angara_sys.index_stats) are not part of the current user-facing SQL surface. Use EXPLAIN to verify index usage.

Слои архитектуры и governance зависимостей

Статус

Модель слоёв стабилизирована (active). Изменения вносятся только через RFC.

Цель: иметь простую, проверяемую модель слоёв и зависимостей, чтобы изменения не размывали границы.

Слои (рабочая модель)

  1. Core engine (angarabase): семантика SQL, транзакции, storage API, WAL/recovery primitives.
  2. Adapters (angarabased, будущие): pgwire/HTTP/admin surfaces, преобразование протоколов.
  3. Tooling (angara-cli, CI, harnesses): утилиты, runners, тестовые harness’ы.
  4. Distribution/Packaging tooling (packaging, release scripts): release artifacts, signatures, package manifests, publication scripts.
  5. 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

SQLSTATENameContext
0A000feature_not_supportedUnsupported SQL forms, complex RLS predicates in IR mode, server-side predicates on client-encrypted columns (randomized), unsupported RLS mask expressions
22023invalid_parameter_valueInvalid stats_level_max values, invalid SET BREAK_GLASS ... TTL=... values
23514check_violationInsert into partitioned parent with no matching child/DEFAULT partition
25001active_sql_transactionSET SESSION CONTEXT inside an active transaction
42501insufficient_privilegeUser/role/policy/break-glass actions without required roles, protected SQL without SecurityContext
42809wrong_object_typeDML 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.mdKI-2026-001.

Checksum verification

  • If on-disk page verification fails, read path fails closed with explicit checksum mismatch diagnostics.
  • 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:

  • UPDATE on an append-only table,
  • DELETE on 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_privilege is expected when user/role/policy/break-glass actions are executed without required roles.
  • 22023 invalid_parameter_value is expected for invalid SET BREAK_GLASS ... TTL=... values (missing/zero/exceeds max TTL).
  • 25001 active_sql_transaction is expected for SET SESSION CONTEXT inside an active transaction.

Session security context

  • 42501 insufficient_privilege is expected in scram/cert modes when protected SQL executes without a session SecurityContext.
  • 0A000 feature_not_supported is expected in IR mode for unsupported complex RLS predicates (bounded fail-closed planner/IR contract).

Client encryption and RLS masks

  • 0A000 feature_not_supported is expected for unsupported server-side predicates on client-encrypted columns in randomized mode.
  • 0A000 feature_not_supported is expected for unsupported RLS mask expressions outside v1 bounded forms (partial, nullify).

Дальше

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

CategoryDescription
InvalidInputClient passed invalid parameters or malformed query
TransactionControlTransaction state errors (serialization failures, conflicts)
AccessControlInsufficient privileges
ResourceLimitResource exhaustion (memory, connections, locks)
InternalErrorInternal engine errors (bugs, invariant violations)
IoErrorDisk/network I/O errors

Error Code Registry

EngineErrorKindPG SQLSTATEPG Code NameCategoryDescription
InvalidParameter22023invalid_parameter_valueInvalidInputCaller passed an invalid parameter (validation failure inside the engine).
TransactionAborted40001serialization_failureTransactionControlTransaction aborted by the engine (serialization failure, conflict, …).
LockTimeout55P03lock_not_availableResourceLimitLock acquisition exceeded the configured timeout.
AccessDenied42501insufficient_privilegeAccessControlAuthorization / RBAC denial inside the engine.
InternalErrorXX000internal_errorInternalErrorCatch-all internal error (unexpected state, broken invariant).
DuplicateKey23505unique_violationInvalidInputUnique-key violation (catalogued for clean SQLSTATE mapping).
ConstraintViolation23000integrity_constraint_violationInvalidInputGeneric constraint violation (FK, CHECK, NOT NULL, …).
NotFound42704undefined_objectInvalidInputObject does not exist (table, schema, row, …).
IoError58030io_errorIoErrorI/O error from storage / WAL / recovery layer.
ResourceExhausted53000insufficient_resourcesResourceLimitResource exhaustion (memory limits, connection limits, …).
QosQueueFull53600qos_queue_fullResourceLimitQoS queue full — per-level cap on concurrent/queued requests exceeded.
FeatureNotSupported0A000feature_not_supportedInvalidInputRequested feature is not supported by this version of AngaraBase.
UndefinedFunction42883undefined_functionInvalidInputOperator or function not found for the given argument types.
InvalidColumnReference42P10invalid_column_referenceInvalidInputInvalid column reference (e.g., ORDER BY ordinal out of range).
SyntaxError42601syntax_errorInvalidInputSQL syntax error in the submitted query.
NoActiveSqlTransaction25P01no_active_sql_transactionTransactionControlCommand requires an active transaction but none is in progress.
ActiveSqlTransaction25001active_sql_transactionTransactionControlCommand cannot be executed within an active transaction block.
ReadOnlySqlTransaction25006read_only_sql_transactionTransactionControlWrite operation attempted in a read-only transaction.
IdleInTransactionTimeout57P01idle_in_transaction_session_timeoutResourceLimitSession 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 via SET without server restart
  • Dynamic: 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 SET time with SQLSTATE 22023.

NameDefaultScopeDynamicHas ValidatorDescription
max_connections100instancefalseyesMaximum number of concurrent client connections (0 = unlimited).
server.addr127.0.0.1:5152instancefalsenopgwire bind address in host:port format (e.g. 127.0.0.1:5152 or 0.0.0.0:5432)
server.host``instancefalsenoDEPRECATED: use server.addr instead. pgwire bind host
server.port``instancefalsenoDEPRECATED: use server.addr instead. pgwire bind port
storage.data_directory``instancefalsenostorage data dir (immutable)
storage.transaction_log_directory``instancefalsenotxlog dir (immutable)
transaction_log.backendfileinstancefalsenotransaction log backend (noop/file/file_bin)
transaction_log.durabilitystrictinstancefalsenotransaction log durability (strict/relaxed/group_commit)
transaction_log.fsynctrueinstancefalseyestransaction log fsync (strict mode; dev override)
transaction_log.group_commit_v2falseinstancefalseyesgroup_commit waiter batching toggle
transaction_log.wal_compressionoffinstancefalsenoWAL compression mode: off|lz4|zstd
transaction_log.wal_compression_min_bytes256instancefalseyesminimum payload bytes for compression attempt
transaction_log.wal_archive_enablefalseinstancefalseyesappend durable WAL bytes to archive stream
transaction_log.wal_archive_dir/tmp/angarabase-dev/wal_archiveinstancefalsenoWAL archive directory path
security.dev_modefalseinstancefalseyesdevelopment mode preset
security.allow_insecurefalseinstancefalseyesallow insecure combinations (explicit override)
security.tde_enabledfalseinstancefalseyestransparent data encryption toggle
security.tde_master_key_id``instancefalsenonon-secret TDE master key identifier
security.tde_last_rotation_unix0instancefalseyeslast TDE key rotation time (unix seconds)
tls.enabledfalseinstancefalseyesenable pgwire TLS
tls.cert_path``instancefalsenoTLS cert path (PEM)
tls.key_path``instancefalsenoTLS key path (PEM)
tls.require_on_remote_bindfalseinstancetrueyesrefuse remote bind without TLS
tls.gost_enabledfalseinstancefalseyesenable GOST crypto profiles (opt-in, fail-closed)
tls.gost_cipher_suites``instancefalsenoGOST cipher suites preference (TLS 1.2 + GOST ciphers)
auth.modetrustinstancefalsenopgwire auth mode
rbac.admin_users``instancetruenoseed list of RBAC admins
audit.log_path``instancetruenoaudit JSONL sink path
audit.dml_modeoffinstancetruenoaudit DML policy mode: off|allowlist|denylist
audit.dml_allowlist``instancetruenoaudit DML allowlist (comma-separated table refs)
audit.dml_denylist``instancetruenoaudit DML denylist (comma-separated table refs)
audit.export_json_enabledfalseinstancetrueyesenable JSON audit export worker
audit.export_syslog_enabledfalseinstancetrueyesenable Syslog audit export worker
audit.export_rate_limit_rps10instancetrueyesaudit export max events per second
ops.allow_sql_shutdownfalseinstancetrueyesenable SQL shutdown trigger
ops.shutdown_timeout_ms1000instancetrueyesgraceful shutdown timeout (ms)
ops.metrics_addr``instancefalsenometrics bind addr
ops.admin_addr``instancefalsenoadmin API bind addr
lock_timeout0sessiontrueyessession lock timeout (ms); 0=off
statement_timeout0sessiontrueyesstatement execution timeout (ms); 0=off
angara.consumer_id``sessiontruenooptional logical consumer identifier for the session
sql.execution_modeautoinstancetruenoSQL execution mode: ir_auto|ir_only|ir_strict|force_vector|force_row
sql.parallel.dop_cap_global4instancetrueyesglobal cap for parallel workers available to SQL runtime
sql.parallel.dop_cap_query2instancetrueyesper-query cap for SQL parallel workers
aqp_enabledtrueinstancetrueyesadaptive query processing global enable flag
aqp_modeconservativeinstancetruenoadaptive mode: conservative|aggressive
aqp_min_query_time_ms100instancetrueyesminimum query latency for learning
aqp_learning_rate0.1instancetruenoAQP EMA learning rate
aqp_max_correction100.0instancetruenomax correction multiplier
aqp_memory_feedback_limit_mb1024instancetrueyesglobal memory feedback cap in MB
aqp_variance_threshold10.0instancetruenovariance threshold to disable unstable corrections
aqp_correction_cache_mb64instancetrueyesin-memory correction cache budget in MB
aqp_store_capacity_mb1024instancetrueyesAQP advisory store capacity budget in MB
learned_optimizer_enabledfalseinstancetrueyeslearned optimizer master switch
learned_optimizer_modeactiveinstancetruenolearned optimizer mode: active|shadow
learned_optimizer_timeout_us50instancetrueyeslearned predict timeout per operator in microseconds
learned_optimizer_memory_limit_mb64instancetrueyeslearned model in-memory budget in MB
learned_optimizer_confidence_threshold0.5instancetruenoglobal confidence floor for learned predictions
learned_optimizer_max_nodes_per_query20instancetrueyesmaximum learned inference calls per query
learned_optimizer_regression_window1000instancetrueyesrolling window size for regression detection
txn.max_write_set_pages65536instancefalseyesmax pages modified by one txn
txn.max_write_set_bytes536870912instancefalseyesmax bytes modified by one txn
buffer_pool.uncommitted_pages_ratio_hard0.5instancefalsenohard limit for buffer-pool fraction of frames carrying uncommitted page-image deltas
buffer_pool.backpressure.modeblockinstancefalsenobackpressure mode: block|fail_fast
buffer_pool.backpressure.timeout_ms5000instancefalseyesmax wait time in block mode
wal.vlf_enablefalseinstancetrueyesenable Variable Length Files for WAL
wal.max_size_mb1024instancetrueyesmaximum WAL file size in MB
wal.vlf_size_mb64instancetrueyesVLF segment size in MB
wal.init_vlfs4instancetrueyesinitial number of VLF segments
execution.modeautoinstancetruenoSQL execution mode (auto/force_vector/force_row)
execution.vector_batch_size4096instancetrueyesvector execution batch size
execution.query_memory_limit_mb256instancetrueyesper-query memory limit in MB
aqp.enabledtrueinstancetrueyesenable Adaptive Query Processing
aqp.modeconservativeinstancetruenoAQP mode (conservative/aggressive)
aqp.min_query_time_ms100instancetrueyesminimum query time for AQP feedback
aqp.learning_rate0.1instancetruenoAQP EMA learning rate
aqp.max_correction100.0instancetruenomaximum AQP correction multiplier
aqp.variance_threshold10.0instancetruenovariance threshold for unstable corrections
aqp.correction_cache_mb64instancetrueyesAQP correction cache size in MB
aqp.store_capacity_mb1024instancetrueyesAQP store capacity in MB
diagnostics.log_min_duration_ms-1instancetrueyesslow query log threshold in ms (-1=disabled)
diagnostics.log_query_textfalseinstancetrueyesinclude query text in slow log
diagnostics.stat_statements_max1024instancetrueyesmax stat_statements entries (0=disabled)
checkpoint.dirty_track_enabledtrueinstancefalseyesEnable 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_levelinfoinstancetrueyesstructured 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

TypePrometheus KindDescription
GaugegaugePoint-in-time value that can go up or down
CountercounterMonotonically increasing value (always use rate() or increase())
HistogramhistogramDistribution 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 healthy
  • angarabase_buffer_pool_miss_total — cache misses; spikes indicate memory pressure
  • angarabase_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 < 200ms
  • angarabase_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 near max_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 NameTypeLabelsDescription
angarabase_agg_stream_typed_key_totalCounternoneAggregation stream typed-key operations total.
angarabase_aqp_feedback_applied_totalCounternoneAQP correction feedback applied to optimizer total.
angarabase_aqp_feedback_clamped_totalCounternoneAQP correction feedback clamped by bounds total.
angarabase_auto_analyze_triggered_totalCounternoneAuto-analyze triggers total.
angarabase_backpressure_active_sourcesGaugenoneNumber of storage sources currently applying backpressure.
angarabase_buffer_pool_backpressure_activeGaugenoneBuffer pool backpressure currently active (1=yes, 0=no).
angarabase_buffer_pool_backpressure_events_totalCounternoneBuffer pool backpressure events total.
angarabase_buffer_pool_decomp_spill_totalCounternoneBuffer pool decompression spills to disk total.
angarabase_buffer_pool_evict_failed_totalCounternoneBuffer pool page eviction failures total.
angarabase_buffer_pool_hit_ratio_milliGaugenoneBuffer pool hit ratio × 1000 (milli-fraction).
angarabase_buffer_pool_hit_totalCounternoneBuffer pool cache hits total.
angarabase_buffer_pool_miss_totalCounternoneBuffer pool cache misses total.
angarabase_buffer_pool_over_capacity_pagesGaugenonePages loaded above configured buffer pool capacity.
angarabase_buffer_pool_uncommitted_dirty_pagesGaugenoneBuffer pool frames carrying uncommitted page-image deltas.
angarabase_buffer_pool_waiter_wait_secondsHistogramnoneTime buffer pool waiters spend blocked waiting for a free frame.
angarabase_buffer_pool_warmup_aborted_at_cap_totalCounternoneBuffer pool warmup attempts aborted due to capacity limit total.
angarabase_buffer_pool_warmup_completed_pagesGaugenonePages loaded during last completed buffer pool warmup.
angarabase_buffer_pool_warmup_evictions_during_warmup_totalCounternoneEvictions that occurred during buffer pool warmup total.
angarabase_buffer_pool_warmup_pages_totalCounternonePages loaded by buffer pool warmup total.
angarabase_buffer_ring_active_slotsGaugenoneActive buffer ring slots.
angarabase_buffer_ring_created_totalCounternoneBuffer ring slots created total.
angarabase_buffer_ring_dropped_totalCounternoneBuffer ring slots dropped total.
angarabase_buffer_ring_evictions_totalCounternoneBuffer ring evictions total.
angarabase_catalog_snapshot_segments_totalGaugenoneCatalog snapshot segments currently held.
angarabase_chain_read_legacy_fallback_totalCounternoneVersion-chain reads falling back to legacy path total.
angarabase_chain_read_totalCounternoneVersion-chain reads total.
angarabase_checkpoint_aborted_totalCounternoneCheckpoints aborted total.
angarabase_checkpoint_dirty_pagesGaugenoneDirty pages pending checkpoint flush.
angarabase_checkpoint_dirty_pages_leq_targetGaugenoneDirty pages at or below checkpoint target (1=yes, 0=no).
angarabase_checkpoint_errors_totalCounternoneCheckpoint errors total.
angarabase_checkpoint_index_flush_errors_totalCounternoneIndex flush errors during checkpoint total.
angarabase_checkpoint_target_lsn_currentGaugenoneCurrent checkpoint target LSN.
angarabase_checkpoint_scan_pages_totalCounternoneTotal pages inspected during checkpoint (dirty bitmap: O(dirty pages); full scan: O(total pages)).
angarabase_checkpoint_totalCounternoneCheckpoints completed total.
angarabase_column_cache_evictions_totalCounternoneColumnar column cache evictions total.
angarabase_column_cache_oom_rejected_totalCounternoneColumn cache allocations rejected due to OOM total.
angarabase_columnar_compaction_bytes_read_totalCounternoneBytes read during columnar compaction total.
angarabase_columnar_compaction_bytes_written_totalCounternoneBytes written during columnar compaction total.
angarabase_columnar_compaction_totalCounternoneColumnar compaction runs total.
angarabase_columnar_delete_vectors_applied_rows_totalCounternoneRows affected by columnar delete vectors total.
angarabase_columnar_delete_vectors_attached_totalCounternoneColumnar delete vectors attached total.
angarabase_columnar_direct_io_fallback_totalCounternoneColumnar reads falling back from direct I/O total.
angarabase_columnar_dml_duration_msHistogramnoneColumnar DML operation duration in milliseconds.
angarabase_columnar_manifest_init_failed_totalCounternoneColumnar manifest initialisation failures total.
angarabase_committed_version_exhausted_totalCounternoneCommitted version slot exhaustion events total.
angarabase_compress_duration_us_totalCounternoneCumulative compression time in microseconds.
angarabase_compress_ops_totalCounternoneCompression operations total.
angarabase_compression_downgrade_totalCounternoneCompression algorithm downgrades (payload too small) total.
angarabase_compression_ratio_ema_milliGaugenoneEMA compression ratio × 1000.
angarabase_config_unknown_keys_totalCounternoneUnknown configuration keys encountered at startup total.
angarabase_deadlock_detected_totalCounternoneDeadlocks detected by the lock manager total.
angarabase_decompress_duration_us_totalCounternoneCumulative decompression time in microseconds.
angarabase_decompress_ops_totalCounternoneDecompression operations total.
angarabase_deployment_probe_cgroup_v1GaugenoneDeployment probe detected cgroup v1 (1=yes, 0=no).
angarabase_deployment_probe_cgroup_v2GaugenoneDeployment probe detected cgroup v2 (1=yes, 0=no).
angarabase_deployment_probe_fallback_totalCounternoneDeployment probe fallback events total.
angarabase_deployment_probe_override_blocked_totalCounternoneDeployment probe override blocked events total.
angarabase_deployment_probe_runs_totalCounternoneDeployment probe runs total.
angarabase_deployment_profile_bare_metal_totalCounternoneDeployments on bare-metal profile total.
angarabase_deployment_profile_container_totalCounternoneDeployments on container profile total.
angarabase_engine_optimizer_catalog_row_count_fallback_totalCounternoneOptimizer catalog row-count fallback events total.
angarabase_engine_optimizer_index_scan_chosen_totalCounternoneOptimizer chose index scan total.
angarabase_engine_optimizer_small_table_seq_scan_totalCounternoneOptimizer chose sequential scan for small table total.
angarabase_engine_optimizer_stale_stats_fallback_totalCounternoneOptimizer fell back due to stale statistics total.
angarabase_expr_ir_arena_chunks_totalCounternoneExpression IR arena chunks allocated total.
angarabase_expr_ir_arena_released_bytes_totalCounternoneExpression IR arena bytes released total.
angarabase_expr_ir_arena_reserved_bytes_totalCounternoneExpression IR arena bytes reserved total.
angarabase_expr_ir_fallback_totalCounternoneExpression IR evaluation fallbacks total.
angarabase_fsync_timeout_totalCounternonefsync timeout events total.
angarabase_gc_background_ticks_totalCounternoneGC background tick cycles total.
angarabase_gc_compact_calls_totalCounternoneGC compaction calls total.
angarabase_gc_compact_history_versions_removed_totalCounternoneOld MVCC history versions removed by GC compaction total.
angarabase_gc_compact_slice_duration_ms_bucket_1CounternoneGC compact slice duration histogram bucket ≤1ms.
angarabase_gc_compact_slice_duration_ms_bucket_10CounternoneGC compact slice duration histogram bucket ≤10ms.
angarabase_gc_compact_slice_duration_ms_bucket_100CounternoneGC compact slice duration histogram bucket ≤100ms.
angarabase_gc_compact_slice_duration_ms_bucket_5CounternoneGC compact slice duration histogram bucket ≤5ms.
angarabase_gc_compact_slice_duration_ms_bucket_50CounternoneGC compact slice duration histogram bucket ≤50ms.
angarabase_gc_compact_slice_duration_ms_bucket_500CounternoneGC compact slice duration histogram bucket ≤500ms.
angarabase_gc_compact_slice_duration_ms_bucket_infCounternoneGC compact slice duration histogram bucket +Inf.
angarabase_gc_compact_slice_duration_ms_countCounternoneGC compact slice duration histogram observation count.
angarabase_gc_compact_slice_duration_ms_sumCounternoneGC compact slice duration histogram sum (ms).
angarabase_gc_compact_slices_totalCounternoneGC compaction slices processed total.
angarabase_gc_compact_tables_removed_totalCounternoneTables fully removed by GC compaction total.
angarabase_gc_compact_tables_scanned_totalCounternoneTables scanned by GC compaction total.
angarabase_gc_compact_versions_removed_totalCounternoneMVCC versions removed by GC compaction total.
angarabase_gc_tuning_bloat_ratio_percentGaugenoneGC tuning: current bloat ratio estimate (percent).
angarabase_gc_tuning_budget_tuples_per_cycleGaugenoneGC tuning: adaptive budget tuples per cycle.
angarabase_gc_tuning_cycle_duration_ms_lastGaugenoneLast GC tuning cycle duration in ms.
angarabase_gc_tuning_decision_total_decreaseCounternoneGC tuning decisions to decrease budget total.
angarabase_gc_tuning_decision_total_holdCounternoneGC tuning decisions to hold budget total.
angarabase_gc_tuning_decision_total_increaseCounternoneGC tuning decisions to increase budget total.
angarabase_gc_tuning_min_active_epoch_lagGaugenoneMinimum active epoch lag seen by GC tuner.
angarabase_gc_tuning_sleep_msGaugenoneGC tuner current sleep interval in ms.
angarabase_gc_watermark_snapshotGaugenoneGC safe watermark snapshot epoch.
angarabase_gc_pages_compacted_totalCounternoneHeap pages compacted by GcWorker (dead-tuple reclaim) total.
angarabase_gc_dead_tuples_reclaimed_totalCounternoneDead tuple slots reclaimed by GcWorker total.
angarabase_group_commit_batches_totalCounternoneWAL group-commit batches flushed total.
angarabase_hash_join_build_rows_totalCounternoneHash join build-side rows processed total.
angarabase_hash_join_probe_rows_totalCounternoneHash join probe-side rows processed total.
angarabase_hash_join_spilled_to_nested_loop_totalCounternoneHash joins that spilled and fell back to nested loop total.
angarabase_heap_deletes_totalCounternoneHeap row deletions total.
angarabase_heap_dml_errors_totalCounternoneHeap DML errors total.
angarabase_heap_inserts_totalCounternoneHeap row insertions total.
angarabase_heap_pages_flushed_on_shutdownCounternoneHeap pages flushed during graceful shutdown.
angarabase_heap_point_fetch_fallback_reason_not_found_totalCounternoneHeap point-fetch fallbacks: row not found total.
angarabase_heap_point_fetch_fallback_reason_stale_tid_index_totalCounternoneHeap point-fetch fallbacks: stale TID index total.
angarabase_heap_point_fetch_fallback_totalCounternoneHeap point-fetch fallbacks total.
angarabase_heap_point_fetch_totalCounternoneHeap point-fetch attempts total.
angarabase_heap_tid_index_readyGaugenoneHeap TID index readiness (1=ready, 0=not ready).
angarabase_heap_updates_totalCounternoneHeap row updates total.
angarabase_htap_staleness_msGaugenoneHTAP read-replica staleness in milliseconds.
angarabase_idle_txn_killed_totalCounternoneIdle transactions killed by the idle-timeout janitor total.
angarabase_index_build_aborts_totalCounternoneIndex build aborts total.
angarabase_index_builds_totalCounternoneIndex builds started total.
angarabase_index_deletes_totalCounternoneIndex key deletions total.
angarabase_index_drops_totalCounternoneIndex drop operations total.
angarabase_index_inserts_totalCounternoneIndex key insertions total.
angarabase_index_lookups_totalCounternoneIndex lookup operations total.
angarabase_index_migration_completed_totalCounternoneIndex migrations completed total.
angarabase_index_migration_failed_totalCounternoneIndex migration failures total.
angarabase_index_not_found_totalCounternoneIndex lookup: key not found total.
angarabase_index_only_scan_heap_fetches_totalCounternoneHeap fetches during index-only scans total.
angarabase_index_only_scan_hits_totalCounternoneIndex-only scan hits (no heap fetch required) total.
angarabase_index_pages_totalGaugeindex_nameTotal pages in an index.
angarabase_index_pkey_no_table_id_totalGaugenonePrimary-key index entries with no resolved table ID.
angarabase_index_range_scans_totalCounternoneIndex range scan operations total.
angarabase_index_reject_totalCounternoneIndex operation rejections total.
angarabase_index_restore_empty_labeled_totalCounterindex, dbEmpty index restores (with index+db label) total.
angarabase_index_restore_empty_totalCounternoneEmpty index restores total.
angarabase_index_restore_failed_totalCounterindex, dbIndex restore failures total.
angarabase_index_routing_legacy_totalCounterdbIndex routing via legacy path total.
angarabase_index_scan_rows_fetched_totalCounternoneRows fetched via index scan total.
angarabase_index_stale_tuple_fallbacks_totalCounternoneIndex scan stale-tuple fallbacks total.
angarabase_io_advisor_current_batch_sizeGaugenoneIO advisor current adaptive batch size.
angarabase_io_backend_activeGaugebackendIO backend active (1=active) per backend.
angarabase_io_backend_active_componentGaugecomponent, backendIO backend active per component and backend.
angarabase_io_complete_totalCounteropIO completions total per operation type.
angarabase_io_error_totalCounteropIO errors total per operation type.
angarabase_io_submit_totalCounteropIO submissions total per operation type.
angarabase_io_uring_active_instancesGaugenoneActive io_uring ring instances.
angarabase_io_uring_backpressure_totalCounternoneio_uring backpressure events total.
angarabase_io_uring_cqe_completed_totalCounternoneio_uring CQEs completed total.
angarabase_io_uring_direct_submit_totalCounternoneio_uring direct (non-SQPOLL) submissions total.
angarabase_io_uring_fallback_totalCounternoneio_uring operations falling back to pread/pwrite total.
angarabase_io_uring_inflight_highGaugenoneio_uring high-watermark inflight operations.
angarabase_io_uring_inflight_lowGaugenoneio_uring low-watermark inflight operations.
angarabase_io_uring_parallel_inflight_highGaugenoneio_uring parallel inflight high-watermark.
angarabase_io_uring_parallel_inflight_lowGaugenoneio_uring parallel inflight low-watermark.
angarabase_io_uring_read_fixed_totalCounternoneio_uring fixed-buffer reads total.
angarabase_io_uring_registered_buffers_countGaugenoneio_uring registered buffer count.
angarabase_io_uring_sqe_submitted_totalCounternoneio_uring SQEs submitted total.
angarabase_io_uring_sqpoll_enabledGaugenoneio_uring SQPOLL mode enabled (1=yes, 0=no).
angarabase_io_uring_task_panic_totalCounternoneio_uring task panics total.
angarabase_io_uring_wal_write_error_totalCounternoneio_uring WAL write errors total.
angarabase_io_uring_write_fixed_totalCounternoneio_uring fixed-buffer writes total.
angarabase_ir_ddl_executed_totalCounternoneIR-path DDL statements executed total.
angarabase_ir_dml_executed_totalCounternoneIR-path DML statements executed total.
angarabase_ir_legacy_path_violation_totalCounternoneIR legacy path violations detected total.
angarabase_ir_plan_depth_reject_totalCounternoneIR plans rejected for excessive depth total.
angarabase_ir_plan_executed_totalCounternoneIR plans executed total.
angarabase_l0_blob_bytes_written_totalCounternoneL0 blob bytes written total.
angarabase_l0_blobs_activeGaugenoneActive L0 blobs.
angarabase_legacy_fallback_triggered_totalCounternoneLegacy SQL execution fallbacks triggered total.
angarabase_lock_acquire_totalCounternoneLock acquisitions total.
angarabase_lock_timeout_totalCounternoneLock acquisition timeouts total.
angarabase_manifest_log_appends_totalCounternoneManifest log appends total.
angarabase_manifest_log_checkpoints_totalCounternoneManifest log checkpoints total.
angarabase_manifest_log_replay_records_totalCounternoneManifest log records replayed total.
angarabase_merge_join_executions_totalCounternoneMerge join executions total.
angarabase_mvcc_history_versions_totalGaugenoneTotal MVCC history versions held.
angarabase_notify_delivered_totalCounternoneLISTEN/NOTIFY notifications delivered total.
angarabase_notify_dropped_totalCounternoneLISTEN/NOTIFY notifications dropped total.
angarabase_notify_listeners_activeGaugenoneActive LISTEN subscribers.
angarabase_optimizer_decorrelation_fallback_non_equi_predicate_totalCounternoneOptimizer decorrelation fallback: non-equi predicate total.
angarabase_optimizer_decorrelation_fallback_null_semantics_risk_totalCounternoneOptimizer decorrelation fallback: null semantics risk total.
angarabase_optimizer_decorrelation_fallback_totalCounternoneOptimizer decorrelation fallbacks total.
angarabase_optimizer_decorrelation_fallback_unsafe_pattern_totalCounternoneOptimizer decorrelation fallback: unsafe pattern total.
angarabase_optimizer_dp_fallback_totalCounternoneOptimizer dynamic-programming join-order fallbacks total.
angarabase_optimizer_memo_entriesGaugenoneOptimizer memo table entries (last query).
angarabase_optimizer_multicolumn_pairs_capped_totalCounternoneOptimizer multicolumn pair evaluation capped total.
angarabase_optimizer_queries_totalCounternoneQueries processed by the optimizer total.
angarabase_optimizer_replan_total_aqp_feedbackCounternoneOptimizer replans triggered by AQP feedback total.
angarabase_optimizer_replan_total_forced_fallbackCounternoneOptimizer forced-fallback replans total.
angarabase_optimizer_replan_total_schema_changedCounternoneOptimizer replans due to schema change total.
angarabase_optimizer_replan_total_stats_driftCounternoneOptimizer replans due to stats drift total.
angarabase_optimizer_stale_stats_totalCounternoneOptimizer stale statistics encounters total.
angarabase_optimizer_timeout_totalCounternoneOptimizer timeout events total.
angarabase_orphan_blobs_reclaimed_totalCounternoneOrphan blobs reclaimed by GC total.
angarabase_overlay_rows_evicted_totalCounternoneTX overlay rows evicted total.
angarabase_parallel_agg_totalCounternoneParallel aggregation executions total.
angarabase_parallel_budget_exceeded_totalCounternoneParallel worker budget exceeded events total.
angarabase_parallel_join_admitted_totalCounternoneParallel join operations admitted total.
angarabase_parallel_join_slots_activeGaugenoneActive parallel join slots.
angarabase_parallel_join_throttled_totalCounternoneParallel join operations throttled total.
angarabase_parallel_morsels_stolen_totalCounternoneParallel morsels stolen by work-stealing total.
angarabase_parallel_morsels_totalCounternoneParallel morsels created total.
angarabase_parallel_scan_totalCounternoneParallel scan operations total.
angarabase_parallel_worker_cancel_totalCounternoneParallel worker cancellations total.
angarabase_parallel_worker_starvation_events_totalCounternoneParallel worker starvation events total.
angarabase_parallel_workers_activeGaugenoneCurrently active parallel workers.
angarabase_parallel_workers_denied_by_cap_totalCounternoneParallel worker requests denied by DOP cap total.
angarabase_partition_pruned_branches_totalCounternonePartition branches pruned by predicate pushdown total.
angarabase_partition_route_default_totalCounternonePartition routes to default partition total.
angarabase_partition_route_no_match_totalCounternonePartition routes with no matching partition total.
angarabase_partition_route_ok_totalCounternoneSuccessful partition routes total.
angarabase_pgwire_active_tasksGaugenoneActive pgwire tasks (queries in flight).
angarabase_pgwire_pool_active_workersGaugenoneActive pgwire workers (async spawn_blocking tasks or legacy pool busy workers).
angarabase_pgwire_pool_queue_depthGaugenonepgwire pool pending connection queue depth.
angarabase_pgwire_pool_rejected_totalCounternonepgwire connections rejected by pool limit total.
angarabase_pgwire_simple_queries_totalCounternonepgwire simple-query protocol messages total.
angarabase_pkey_backfill_fail_totalCounternonePrimary-key backfill failures total.
angarabase_pkey_backfill_in_progressGaugenonePrimary-key backfill operations in progress.
angarabase_pkey_backfill_ok_totalCounternonePrimary-key backfill completions total.
angarabase_plan_cache_dml_hit_duration_usHistogramnoneDML plan cache hit latency in microseconds.
angarabase_plan_cache_dml_hits_totalCounternoneDML plan cache hits total.
angarabase_plan_cache_dml_misses_totalCounternoneDML plan cache misses total.
angarabase_plan_cache_dml_param_extract_error_totalCounternoneDML plan cache parameter extraction errors total.
angarabase_plan_cache_dml_schema_miss_totalCounternoneDML plan cache schema mismatch misses total.
angarabase_plan_cache_evictions_totalCounternonePlan cache evictions total.
angarabase_plan_cache_hits_totalCounternonePlan cache hits total.
angarabase_plan_cache_invalidations_totalCounternonePlan cache invalidations total.
angarabase_plan_cache_misses_totalCounternonePlan cache misses total.
angarabase_plan_cache_sizeGaugenoneCurrent plan cache entry count.
angarabase_prefetch_hints_totalCounternonePrefetch hints issued total.
angarabase_projection_pruning_cols_eliminated_totalCounternoneColumns eliminated by projection pruning total.
angarabase_qos_blocking_inflightGaugenoneQoS blocking inflight operations.
angarabase_qos_priority_inherit_totalCounterfrom, toQoS priority inheritance events total.
angarabase_qos_queued_background_totalCounternoneQoS background-priority requests queued total.
angarabase_qos_queued_critical_totalCounternoneQoS critical-priority requests queued total.
angarabase_qos_queued_interactive_totalCounternoneQoS interactive-priority requests queued total.
angarabase_qos_rejected_background_totalCounternoneQoS background-priority requests rejected total.
angarabase_qos_rejected_critical_totalCounternoneQoS critical-priority requests rejected total.
angarabase_qos_rejected_interactive_totalCounternoneQoS interactive-priority requests rejected total.
angarabase_query_exec_duration_msHistogramnoneQuery execution duration in milliseconds.
angarabase_query_exec_totalCounteroutcome, classQuery executions total by outcome and class.
angarabase_query_feedback_events_totalCounterreasonQuery feedback events emitted total.
angarabase_query_store_entries_totalGaugenoneQuery store current entry count.
angarabase_query_store_evictions_totalCounternoneQuery store evictions total.
angarabase_query_store_intervals_flushed_totalCounternoneQuery store intervals flushed to WAL total.
angarabase_query_store_modeGaugenoneQuery store current mode (encoded integer).
angarabase_query_store_plans_totalGaugenoneQuery store current plan count.
angarabase_query_store_regressions_detected_totalCounternoneQuery regressions detected by the query store total.
angarabase_query_store_rotations_totalCounternoneQuery store interval rotations total.
angarabase_query_store_wal_errors_totalCounternoneQuery store WAL write errors total.
angarabase_recovery_analysis_msGaugenoneRecovery analysis phase duration in ms.
angarabase_recovery_clr_recordsCounternoneRecovery CLR (compensation log) records replayed total.
angarabase_recovery_dirty_pagesGaugenoneDirty pages remaining after recovery redo.
angarabase_recovery_redo_recordsCounternoneRecovery redo records applied total.
angarabase_recovery_replay_pages_applied_totalCounternoneRecovery page replay: pages applied total.
angarabase_recovery_replay_pages_runs_totalCounternoneRecovery page replay runs total.
angarabase_recovery_replay_pages_skipped_totalCounternoneRecovery page replay: pages skipped total.
angarabase_recovery_undo_txnsCounternoneTransactions rolled back during recovery total.
angarabase_scan_stream_batches_totalCounternoneScan stream batches produced total.
angarabase_scan_stream_fallback_totalCounternoneScan stream fallbacks to row-by-row total.
angarabase_scan_stream_materialize_totalCounterreasonScan stream materialise operations total by reason.
angarabase_sequence_currval_totalCounternoneCURRVAL calls total.
angarabase_sequence_nextval_totalCounternoneNEXTVAL calls total.
angarabase_sequence_overflow_totalCounternoneSequence overflow events total.
angarabase_sequence_owned_create_failed_totalCounternoneOwned sequence create failures total.
angarabase_sequence_owned_lazy_migration_totalCounternoneOwned sequence lazy migrations total.
angarabase_sequence_owned_nextval_totalCounternoneOwned sequence NEXTVAL calls total.
angarabase_sequence_setval_totalCounternoneSETVAL calls total.
angarabase_server_connections_accepted_totalCounternoneServer connections accepted total.
angarabase_server_connections_activeGaugenoneCurrently active server connections.
angarabase_session_claims_set_totalCounternoneSession JWT claim SET operations total.
angarabase_shutdown_dirty_pages_remainingGaugenoneDirty pages remaining at shutdown start.
angarabase_slow_query_totalCounternoneSlow queries exceeding log_min_duration_ms total.
angarabase_spawn_blocking_activeGaugenoneActive spawn_blocking tasks.
angarabase_spawn_blocking_maxGaugenoneMaximum observed spawn_blocking concurrency.
angarabase_spill_bytes_in_useGaugenoneSpill storage bytes currently in use.
angarabase_spill_bytes_totalCounternoneTotal bytes spilled to disk.
angarabase_spill_direct_io_supportedGaugenoneSpill direct I/O supported on this filesystem (1=yes).
angarabase_spill_files_totalCounternoneSpill files created total.
angarabase_spill_hash_join_bloom_filtered_probe_rows_totalCounternoneHash join bloom-filtered probe rows total.
angarabase_spill_hash_join_recursion_depth_overflow_totalCounternoneHash join recursion depth overflow events total.
angarabase_spill_hash_join_recursive_partitions_totalCounternoneRecursive spill partitions created total.
angarabase_spill_hash_join_skew_fallback_totalCounternoneHash join skew fallbacks total.
angarabase_spill_otmpfile_with_direct_supportedGaugenoneO_TMPFILE with direct I/O supported (1=yes).
angarabase_spill_soft_quota_reached_totalCounternoneSpill soft quota reached events total.
angarabase_sql_correlated_budget_reject_totalCounternoneCorrelated subquery budget rejections total.
angarabase_sql_cross_join_budget_reject_totalCounternoneCross join budget rejections total.
angarabase_sql_default_nextval_reject_totalCounternoneDEFAULT NEXTVAL rejections total.
angarabase_sql_full_join_fallback_totalCounternoneFULL JOIN fallbacks total.
angarabase_sql_identity_override_reject_totalCounternoneIDENTITY ALWAYS override rejections total.
angarabase_sql_join_rows_produced_cross_totalCounternoneRows produced by cross joins total.
angarabase_sql_join_rows_produced_full_totalCounternoneRows produced by full outer joins total.
angarabase_sql_join_rows_produced_inner_totalCounternoneRows produced by inner joins total.
angarabase_sql_join_rows_produced_lateral_totalCounternoneRows produced by lateral joins total.
angarabase_sql_join_rows_produced_left_totalCounternoneRows produced by left outer joins total.
angarabase_sql_join_rows_produced_right_totalCounternoneRows produced by right outer joins total.
angarabase_sql_routing_totalCounterdecisionSQL routing decisions total by decision type.
angarabase_sql_scalar_subquery_cardinality_violations_totalCounternoneScalar subquery cardinality violations total.
angarabase_sql_sequence_allocations_identity_always_totalCounternoneSequence allocations for IDENTITY ALWAYS columns total.
angarabase_sql_sequence_allocations_identity_by_default_totalCounternoneSequence allocations for IDENTITY BY DEFAULT columns total.
angarabase_sql_sequence_allocations_serial_totalCounternoneSequence allocations for SERIAL columns total.
angarabase_sql_upsert_conflict_totalCounternoneUPSERT conflict events total.
angarabase_sql_upsert_do_nothing_totalCounternoneUPSERT ON CONFLICT DO NOTHING events total.
angarabase_sql_upsert_do_update_totalCounternoneUPSERT ON CONFLICT DO UPDATE events total.
angarabase_stat_statements_entries_currentGaugenoneCurrent stat_statements entry count.
angarabase_stat_statements_evicted_totalCounternonestat_statements LRU evictions total (high rate → literal normalization gap).
angarabase_storage_backpressure_commit_rejected_totalCounternoneCommits rejected by storage backpressure total.
angarabase_storage_backpressure_events_totalCounternoneStorage backpressure events total.
angarabase_storage_cached_pages_totalGaugenonePages currently cached in the storage layer.
angarabase_storage_dirty_pages_totalGaugenoneTotal dirty pages in the storage layer.
angarabase_storage_flush_append_totalCounternoneStorage flush append operations total.
angarabase_storage_flush_bytes_totalCounternoneStorage flush bytes written total.
angarabase_storage_flush_duration_secondsHistogramnoneStorage flush operation duration in seconds.
angarabase_storage_flush_eviction_duration_ms_lastGaugenoneLast storage flush eviction duration in ms.
angarabase_storage_flush_full_totalCounternoneStorage full flushes total.
angarabase_storage_flush_ok_totalCounternoneSuccessful storage flush operations total.
angarabase_storage_flush_skipped_page_lsn_ahead_totalCounternoneStorage flush skips: page LSN ahead of flush LSN total.
angarabase_storage_flush_skipped_pinned_totalCounternoneStorage flush skips: page pinned total.
angarabase_storage_flush_skipped_uncommitted_totalCounternoneStorage flush skips: uncommitted page total.
angarabase_storage_io_read_duration_msHistogramnoneStorage I/O read duration in milliseconds.
angarabase_storage_io_write_duration_msHistogramnoneStorage I/O write duration in milliseconds.
angarabase_storage_per_table_engine_fallback_totalCounternonePer-table engine fallback events total.
angarabase_storage_per_table_engines_countGaugenoneNumber of per-table storage engine overrides.
angarabase_storage_scan_errors_totalGaugenoneStorage scan errors total.
angarabase_storage_sync_data_totalCounternoneStorage data sync operations total.
angarabase_stream_entries_totalCounternoneStream (CDC) entries published total.
angarabase_stream_subscriptions_activeGaugenoneActive stream subscriptions.
angarabase_syscatalog_db_lazy_load_duration_ms_lastGaugenoneLast system-catalog lazy-load duration in ms.
angarabase_syscatalog_db_unavailable_totalCounternoneSystem-catalog DB unavailable events total.
angarabase_syscatalog_global_baseline_load_duration_ms_lastGaugenoneLast system-catalog global baseline load duration in ms.
angarabase_table_lock_contention_totalCounternoneTable-level lock contention events total.
angarabase_transaction_log_bytes_appended_totalCounternoneWAL bytes appended total.
angarabase_transaction_log_checkpoint_chain_broken_totalCounternoneWAL checkpoint chain breaks total.
angarabase_transaction_log_checkpoint_end_invalid_totalCounternoneInvalid WAL checkpoint-end records total.
angarabase_transaction_log_checkpoint_end_valid_totalCounternoneValid WAL checkpoint-end records total.
angarabase_transaction_log_durable_lsnGaugenoneWAL durable (fsync-confirmed) LSN.
angarabase_transaction_log_flush_lsnGaugenoneWAL flush (write-confirmed) LSN.
angarabase_transaction_log_group_commit_pending_lsnGaugenoneWAL group-commit pending LSN.
angarabase_transaction_log_group_commit_pumps_totalCounternoneWAL group-commit pump iterations total.
angarabase_transaction_log_lag_commit_minus_durable_lsnGaugenoneWAL lag: commit LSN minus durable LSN.
angarabase_transaction_log_lag_flush_minus_durable_lsnGaugenoneWAL lag: flush LSN minus durable LSN.
angarabase_transaction_log_lag_pending_minus_durable_lsnGaugenoneWAL lag: pending LSN minus durable LSN.
angarabase_transaction_log_last_checkpoint_idGaugenoneWAL last checkpoint identifier.
angarabase_transaction_log_last_checkpoint_target_lsnGaugenoneWAL last checkpoint target LSN.
angarabase_transaction_log_last_commit_lsnGaugenoneWAL last commit LSN.
angarabase_transaction_log_records_appended_totalCounternoneWAL records appended total.
angarabase_transaction_log_scan_stop_reason_total_bad_crcCounternoneWAL scan stopped: bad CRC total.
angarabase_transaction_log_scan_stop_reason_total_bad_lenCounternoneWAL scan stopped: bad record length total.
angarabase_transaction_log_scan_stop_reason_total_bad_magicCounternoneWAL scan stopped: bad magic bytes total.
angarabase_transaction_log_scan_stop_reason_total_bad_versionCounternoneWAL scan stopped: bad version total.
angarabase_transaction_log_scan_stop_reason_total_partial_recordCounternoneWAL scan stopped: partial record total.
angarabase_tx_overlay_dataset_bytes_totalGaugenoneTX overlay dataset bytes in use.
angarabase_tx_overlay_dataset_limit_exceeded_totalCounternoneTX overlay dataset limit exceeded events total.
angarabase_txn_active_countGaugenoneCurrently active transactions.
angarabase_txn_begin_totalCounternoneTransactions begun total.
angarabase_txn_commit_conflicts_totalCounternoneTransaction commit conflicts (serialization failures) total.
angarabase_txn_commit_epoch_currentGaugenoneCurrent transaction commit epoch.
angarabase_txn_commit_epoch_exhausted_totalCounternoneTransaction commit epoch exhaustion events total.
angarabase_txn_commit_totalCounternoneTransactions committed total.
angarabase_txn_id_exhausted_totalCounternoneTransaction ID exhaustion events total.
angarabase_txn_long_snapshot_hard_totalCounternoneLong-running snapshot hard-limit violations total.
angarabase_txn_long_snapshot_warn_totalCounternoneLong-running snapshot warnings total.
angarabase_txn_oldest_snapshot_age_secondsGaugenoneAge of the oldest active snapshot in seconds.
angarabase_txn_release_savepoint_totalCounternoneRELEASE SAVEPOINT calls total.
angarabase_txn_rollback_to_savepoint_totalCounternoneROLLBACK TO SAVEPOINT calls total.
angarabase_txn_rollback_totalCounternoneTransactions rolled back total.
angarabase_txn_savepoint_totalCounternoneSAVEPOINT calls total.
angarabase_txn_watermark_min_activeGaugenoneMinimum active transaction watermark.
angarabase_txn_watermark_safe_gcGaugenoneSafe GC watermark (all txns below this epoch are committed/aborted).
angarabase_txn_watermark_safe_gc_lag_snapshotsGaugenoneNumber of snapshots lagging behind the safe GC watermark.
angarabase_txn_write_set_limit_exceeded_totalCounternoneTransactions rejected for exceeding write-set size limit total.
angarabase_txn_write_set_pages_maxGaugenoneMaximum write-set pages per transaction configuration.
angarabase_undo_append_rejected_totalCounternoneUndo log append rejections total.
angarabase_undo_file_bytesGaugenoneUndo file size in bytes.
angarabase_undo_gc_truncations_totalCounternoneUndo GC truncations total.
angarabase_undo_segments_totalGaugenoneTotal undo segments.
angarabase_undo_store_bytesGaugenoneUndo store bytes in use.
angarabase_uptime_secondsGaugenoneServer uptime in seconds.
angarabase_vector_batches_produced_totalCounternoneVectorised execution batches produced total.
angarabase_vector_columnar_native_totalCounternoneVector aggregate executions via native columnar batch pipeline.
angarabase_columnar_batched_scan_batches_totalCounternoneColumnar segment batches consumed by vector-native batched scans.
angarabase_columnar_segments_pruned_totalCounternoneColumnar segments pruned by zone-map predicate pushdown before blob I/O.
angarabase_columnar_filtered_agg_late_mat_totalCounternoneFiltered columnar aggregate scans using predicate-first late materialization.
angarabase_vector_fallback_totalCounternoneVectorised execution fallbacks to row mode total.
angarabase_vector_memory_budget_exceeded_totalCounternoneVector execution memory budget exceeded events total.
angarabase_vector_rows_produced_totalCounternoneRows produced by vectorised execution total.
angarabase_version_arena_capacity_exceeded_totalCounternoneVersion arena capacity exceeded events total.
angarabase_version_chain_gc_removed_heads_totalCounternoneVersion chain GC: removed head entries total.
angarabase_version_chain_rebuild_from_wal_totalCounternoneVersion chains rebuilt from WAL during recovery total.
angarabase_version_head_map_sizeGaugenoneVersion head map current entry count.
angarabase_wal_decompressed_records_totalCounternoneWAL records decompressed total.
angarabase_wal_decompression_errors_totalCounternoneWAL decompression errors total.
angarabase_wal_group_commit_wait_totalCounternoneWAL group-commit waiter events total.
angarabase_wal_lsn_drift_resets_totalCounternoneWAL LSN drift reset events total.
angarabase_wal_record_iterator_lsn_order_violations_totalCounternoneWAL record iterator LSN-order violations total.
angarabase_wal_record_iterator_vlf_transitions_totalCounternoneWAL record iterator VLF segment transitions total.
angarabase_wal_sync_wait_totalCounternoneWAL sync waits total.
angarabase_write_hook_duration_ms_totalCounternoneWrite hook cumulative duration in ms.
angarabase_write_hook_invocations_totalCounternoneWrite hook invocations total.
angarabase_write_path_commits_ok_totalCounternoneWrite path successful commits total.
angarabase_write_path_concurrent_waitersGaugenoneCurrent write path concurrent waiters.
angarabase_write_path_lock_free_commits_totalCounternoneLock-free write path commits total.
angarabase_write_path_phase_a_totalCounternoneWrite path phase-A (prepare) completions total.
angarabase_write_path_phase_b_timeout_totalCounternoneWrite path phase-B timeouts total.
angarabase_write_path_phase_b_totalCounternoneWrite path phase-B (commit) completions total.
angarabase_write_path_serialized_commits_totalCounternoneSerialized (non-lock-free) write path commits total.
angarabase_write_write_conflicts_totalCounternoneWrite-write conflicts detected total.

Database Object Types

Типы объектов, которыми управляет каталог AngaraBase. Зарезервированные (недоступные через SQL) типы в список не включены.

Поддерживаемые типы объектов

Object KindDDLsys_catalogStatusDescription
TableCREATE TABLEangara_sys.tablesStableHeap-based relation (primary storage).
IndexCREATE INDEXangara_sys.indexesStableSecondary B-tree index.
SequenceCREATE SEQUENCEangara_sys.sequencesStableAuto-increment generator.
PartitionCREATE TABLE ... PARTITION OFangara_sys.partitionsBaselineRANGE/LIST partition of a partitioned table.
SchemaCREATE SCHEMAangara_sys.namespacesBaselineNamespace for objects.
RoleCREATE ROLEangara_sys.rolesBaselineAuthentication principal (RBAC).
ConstraintALTER TABLE ... ADD CONSTRAINTangara_sys.constraintsBaselineCHECK / UNIQUE / NOT NULL constraint.
ForeignKeyALTER TABLE ... ADD FOREIGN KEY (NOT ENFORCED)angara_sys.constraintsBaselineDeclarative referential constraint; NOT ENFORCED at runtime.

Planned

Запланированы, но пока не доступны через SQL:

  • View — Virtual relation based on a query.
  • Function — User-defined function.

Типы данных SQL

Типы данных, поддерживаемые AngaraBase. Наличие OID в виртуальном pg_catalog (для интроспекции) не означает поддержку — в таблицу ниже включены только реально пригодные к использованию типы.

Поддерживаемые типы

ТипOIDpg_typeofСтатусОписание
bool16boolStableLogical boolean (true/false).
bytea17byteaStableVariable-length binary string.
int820int8Stable64-bit signed integer (bigint).
int423int4Stable32-bit signed integer (integer).
text25textStableVariable-length character string.
float8701float8StableDouble-precision floating-point.
int221int2Baseline16-bit signed integer (smallint).
float4700float4BaselineSingle-precision floating-point (real).
numeric1700numericBaselineExact numeric (Decimal-backed); explicit casts canonicalize.
uuid2950uuidBaselineUniversally unique identifier; explicit casts only.
varchar1043varcharBaselineVariable-length character string (text-backed).
bpchar1042bpcharBaselineCharacter string CHAR(n) (text-backed).
mvarchar46001mvarcharBaseline1C-compatible national VARCHAR: UTF-16LE semantics, case/trailing-space-insensitive collation, mvarchar(N).
date1082dateBaselineCalendar date (text-backed; minimal validation).
timestamp1114timestampBaselineDate and time, no time zone (text-backed).
timestamptz1184timestamptzBaselineDate 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 Stable53000insufficient_resourcesmax_connectionsangarabase_pgwire_pool_rejected_total
QoS admission (concurrent queries) Baseline53600qos_queue_fullangarabase_qos_rejected_critical_totalqos_queue
Per-transaction write set Baseline54023configuration_limit_exceededtxn.max_write_set_bytes
Buffer-pool / commit backpressure Baseline53400insufficient_resourcesbuffer_pool.backpressure.modeangarabase_buffer_pool_backpressure_events_totalbuffer_pool_eviction
Query memory limit Baseline53400insufficient_resourcesexecution.query_memory_limit_mb
Statement timeout Stable57014query_canceledstatement_timeout
Lock wait timeout Stable55P03lock_not_availablelock_timeoutangarabase_lock_timeout_total
Idle-in-transaction timeout Stable57P01idle_in_transaction_session_timeoutangarabase_idle_txn_killed_total
Snapshot too old (UNDO budget) Baseline72000snapshot_too_old
Disk full Stable53100disk_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 используется для повторного применения зафиксированных, но не записанных на диск изменений.

Дальше

Системные таблицы (System Catalog)

Goal: Описание структуры и назначения системных таблиц AngaraBase для мониторинга, диагностики и управления метаданными.

Системный каталог AngaraBase доступен через виртуальную схему sys. Эти таблицы предоставляют информацию о состоянии инстанса, конфигурации и объектах базы данных в реальном времени.

Таблица sys.tables

Содержит метаданные всех таблиц во всех базах данных и схемах.

ПолеТипОписание
db_idstringИдентификатор базы данных.
schema_namestringИмя схемы (обычно public).
table_namestringИмя таблицы.
tablespace_namestringИмя табличного пространства.
storage_enginestringТип движка хранения: row_store (HeapFile), memory (In-memory), htap_row_column.
durabilitystringУровень долговечности (для memory-таблиц): none, logged, snapshotted.
max_rowsuint64Лимит строк (для memory-таблиц).
eviction_policystringПолитика вытеснения (для memory-таблиц): error, fifo, lru, lfu.
checkpoint_interval_msuint64Интервал чекпоинтов в мс (для snapshotted).
current_rowsuint64Текущее количество живых строк (приблизительно).
evictions_totaluint64Счетчик вытесненных строк.
limit_errors_totaluint64Счетчик ошибок превышения лимита строк.
append_onlyboolФлаг режима append-only (устаревший, см. mutation_policy).
mutation_policystringПолитика изменений: unrestricted, no_delete, append_only.

Примечание по Storage Engine

  • row_store: Стандартное хранение на диске (HeapFile).
  • memory: Данные хранятся в оперативной памяти. Долговечность регулируется параметром durability.

Таблица sys.settings

Предоставляет доступ к текущим настройкам конфигурации сервера (Effective Configuration).

ПолеТипОписание
namestringИмя параметра (например, server.addr).
valuestringТекущее эффективное значение.
sourcestringИсточник значения: default, config, bootstrap_env, sql_runtime.
dynamicbooltrue, если параметр можно изменить без перезагрузки.
docstringКраткое описание параметра.

Таблица sys.databases

Список доступных баз данных.

ПолеТипОписание
db_idstringУникальный идентификатор базы данных.
namestringИмя базы данных.

Таблица sys.schemas

Список схем в базах данных.

ПолеТипОписание
db_idstringИдентификатор базы данных.
schema_namestringИмя схемы.

Troubleshooting

  • Симптом: Таблица sys.tables возвращает пустой результат.

  • Причина: У пользователя нет прав на просмотр метаданных или не выбрана база данных (если используется фильтрация).

  • Решение: Проверьте права доступа (RBAC).

  • Симптом: Изменение в sys.settings не применяется.

  • Причина: Параметр имеет dynamic = false или перекрыт переменной окружения (source = bootstrap_env).

  • Решение: Требуется перезагрузка сервера или изменение конфигурации/переменных окружения.

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

IssueCauseSolution
feature_not_supported on connectionClient querying pg_catalogConfigure client to minimize metadata queries
Slow connection setupToo many system queriesUse preferQueryMode=simple
Missing schema informationAngaraBase doesn’t implement full pg_catalogUse direct SQL queries instead of client introspection

Getting Help

If you encounter client compatibility issues not covered here:

  1. Check the Known Issues page
  2. Enable query logging to identify problematic queries
  3. Consult the Support page for additional resources

For additional client-specific configuration tips, see our community documentation.

Дальше

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 коды документированы как ожидаемое поведение.

Дальше

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 Querypsql -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).
  • 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.
  • 5.17 (closed) — SQL Coverage Expansion:
    • highlights: Window functions v0 (ROW_NUMBER, RANK, LAG, LEAD, SUM/COUNT OVER), Set operations (UNION, INTERSECT, EXCEPT), TPC-H partial benchmarks, pgbench read-write support.
  • 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_commit for snapshotted tables.
  • 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.
  • 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).
  • 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.
  • 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), and EXPLAIN ANALYZE parallel join counters (join_build_rows, join_probe_rows).
  • 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.
  • 5.10 (closed) — AngaraVector phase-1:
    • highlights: vector execution mode now covers join/aggregate plan paths and EXPLAIN marks vector operators (VectorHashJoin, VectorAgg) when vector mode is active.
  • 5.9 (closed) — AngaraVector phase-0:
    • highlights: introduced vector batch format baseline (batch_size default 1024), scan/filter/project vector path, and bounded per-query vector memory budget knobs.
  • 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-table checkpoint_interval_ms scheduling.
  • 5.8 (closed) — AngaraMemory phase-1:
    • highlights: durability='logged'|'snapshotted', opt-in eviction_policy='fifo', and SQL-visible memory-table runtime counters in sys.tables.
  • 5.7 (closed) — AngaraMemory phase-0:
    • highlights: storage='memory' table surface, fail-closed max_rows enforcement (54023), and volatile durability='none' restart semantics.
  • 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
  • 5.6.2 (closed) — packaging baseline for operator install path:
    • highlights:
      • portable x86_64-unknown-linux-gnu archive 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
  • 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
  • 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)
  • 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
  • 5.3.1 (closed) — TDE patch for audit-at-rest:
    • highlights: audit sink bytes are encrypted when TDE is enabled, sys.audit_log stays readable with key material, missing key is fail-closed for audit sink read/write
  • 5.3 (closed) — TDE v0 baseline:
    • highlights: fail-closed TDE enablement for page/WAL at-rest encryption, sys.settings metadata-only introspection for key id/rotation timestamp, restore fail-closed without keys
  • 5.2 (closed) — module decomposition phase-1 (.inc.rs elimination, 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 (0A000 on unsupported complexity), mandatory SecurityContext enforcement (42501 in non-trust modes), bounded planner-stage RLS rewrite for IR SELECT, and audit fsync barriers for break-glass lifecycle events
  • 4.25 (closed) — Security Reinforcement Phase 1:
    • highlights: secure --init superuser bootstrap, RLS v0 on reads+writes, break-glass lifecycle, audit chain verification, sys.* security introspection views/functions
  • 4.21 (closed) — AngaraStat Level 2 reservoir stats (bounded):
    • highlights: stats_reservoir_size, Level 2 histogram/MCV surfaces in sys.column_stats
  • 4.22 (closed) — query diagnostics v0:
    • highlights: EXPLAIN/EXPLAIN ANALYZE, slow query log, angara_stat_activity, angara_stat_statements, angara_top_queries()
  • 4.24 (closed) — reliability/efficiency hardening:
    • highlights: REINDEX INDEX, BRIN range-efficiency metric, strict storage startup default, no-auth startup guardrail
  • 4.24.1 (closed) — mutation policy no_delete:
    • highlights: unified mutation_policy, 42809 guards for DELETE/TRUNCATE and PK/FK updates, sys.tables.mutation_policy
  • 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_max surfaces, typed reservoir samples with membership-aware UPDATE/DELETE handling, wait_event_type in angara_stat_activity
  • 4.24.4 (closed) — core decomposition for executor:
    • highlights: internal refactor (ir_executor split into scan/join/aggregate/sort modules), no user-facing SQL/ops contract changes
  • 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>, deterministic 0A000 hygiene):
  • 4.18 (closed) — table partitioning v0 (RANGE/LIST, routing, pruning, per-partition cascade):
  • 4.19 (closed) — append-only table mode v0 (append_only DDL/property, 42809 mutation guards, partition inheritance, rowid watermark):
  • 4.20 (closed) — AngaraStat Level 1 (ndv_approx/min/max/null_count, stats_level_max controls, stats observability):
  • 4.23 (closed) — unified .adb storage path for heap tables:
    • runtime routing fixed: user DB writes go to <db>.adb and <db>.atl (not base.*)
    • backup/restore note updated: operations/backup-and-restore.md

Milestones (testing-ready)

  • 2.3 (closed) — backup/restore baseline is testable:

    • runbook: angarabook/src/operations/backup-restore.md
  • 2.4 (closed) — execution/compat deepening is pinned:

    • known issues remain explicit: angarabook/src/operations/known-issues.md
  • 2.7 (closed) — backup/restore v2 phase 1a is testable (offline/local baseline):

    • AngaraBook page: operations/backup-and-restore.md
  • 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
  • 2.10 (closed) — SysCatalog identity + native sys.* introspection is available:

    • identity file: storage.data_directory/identity_v0.txt
  • 2.11 (closed)pg_catalog semantics are rooted in SysCatalog (trace-driven) + identity rehearsal gate: rehearsal_identity_rm211.sh)

    • compat matrix (truth source): angarabook/src/operations/client-compatibility.md
  • 2.12 (closed) — upgrade rehearsal is wired into nightly discipline + docs anti-drift is enforced:

    • docs validator: docs/validate-docs.sh
  • 2.13 (closed) — code health hardening: prevent god-files growth (touched-file budget gate):

  • 2.14 (closed) — admin remote transport v0 (TCP) + angara-cli remote identity:

    • server: env ANGARABASE_ADMIN_ADDR + crates/angarabased/src/admin_tcp.rs
    • client: angara-cli admin identity --addr <host:port> [--json]
  • 2.15 (closed) — persisted SysCatalog v0: DDL survives restart:

    • persisted catalog file: storage.data_directory/sys_catalog_v0.txt
  • 2.16 (closed) — graceful shutdown contract (bounded):

    • env knob: ANGARABASE_SHUTDOWN_TIMEOUT_MS
  • 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()

Released tags

Список released tags и ссылки на release notes см. в CHANGELOG.md → “Released”.