Знак Taidon: граф состояний над базой данных Документация по локальной версии Taidon

Первое знакомство с sqlrs

Разберитесь в состояниях, экземплярах и рецептах, а затем пройдите первый локальный сценарий.

Проверено для sqlrs v0.2.0-rc.1Исходный код 36e164a9
Зачем нужен sqlrs

sqlrs упрощает эксперименты с воспроизводимыми состояниями SQL-базы. Вместо ручной подготовки общей базы вы описываете рецепт, а sqlrs по запросу создаёт из него изолированные рабочие экземпляры для разработки, тестов и проверки миграций.

Из чего состоит sqlrs

Пользователь работает с одной CLI-утилитой sqlrs. Через одинаковые команды она обращается к выбранному варианту продукта. Этот учебник посвящён локальной версии: движок, кэш состояний и рабочие экземпляры находятся на локальной машине и работают от имени текущего пользователя.

Локальная версия использует Docker или Podman для запуска контейнеров с базой и инструментами подготовки. Для начала достаточно понимать четыре объекта:

Рабочая область (workspace)
Каталог проекта с локальной папкой .sqlrs/. Она задаёт границы доступных файлов и хранит настройки подключения к движку.
Рецепт подготовки (prepare-рецепт)
Команда и её входные файлы: SQL-скрипты, подключаемые psql-файлы или Liquibase changelog. Рецепт должен полностью описывать получение нужной базы.
Состояние (state)
Неизменяемый результат выполнения рецепта. sqlrs может сохранить его в кэше и повторно использовать, пока образ, аргументы и входные файлы не изменились.
Экземпляр (instance)
Изменяемая база, созданная из состояния. Тест или приложение меняет свой экземпляр, не затрагивая состояние и другие экземпляры.

Главная идея: храните рецепт, а не готовую базу

Репозиторий хранит миграции, SQL и короткое описание способа их запуска. Готовые состояния остаются локальными производными данными: sqlrs создаёт их по необходимости, переиспользует подходящие результаты и со временем вытесняет невостребованные состояния из ограниченного кэша. Экземпляры также можно создавать и удалять по мере работы. Поэтому инфраструктуру не приходится вручную пополнять отдельной базой для каждого теста или эксперимента.

Первый локальный сценарий

Установите архив локальной версии Taidon для своей платформы, запустите среду контейнеров и перейдите в каталог учебного проекта. Команда init создаст .sqlrs/config.yaml, выберет доступный способ хранения снимков и запустит локальный движок:

sqlrs init local --snapshot auto
sqlrs status
СоветКогда нужны расширенные параметры init

init также умеет выбирать каталог или образ хранилища, принудительно включать copy, Btrfs или OverlayFS, указывать путь к движку и настраивать Windows через WSL2. Переходите к этим вариантам, только когда автоматический выбор не подходит.

Сокращённый пример sqlrs status
status: ok
endpoint: http://127.0.0.1:…
profile: local
mode: local
workspace: …
container-runtime: ok
cache.stateCount: 0

Значения зависят от машины. Для продолжения важны status: ok, профиль и режим local, найденная рабочая область и готовая среда контейнеров. Строкиcache.* показывают текущее заполнение локального кэша.

Создайте первое состояние и экземпляр

Начнём с той же подготовки, что используется в короткой проверке установки, но пока ничего не будем запускать поверх базы. Команда выбирает образ postgres:16, выполняет SQL и печатает DSN созданного экземпляра:

sqlrs prepare:psql --image postgres:16 -- -c "create table if not exists smoke_check(id int); insert into smoke_check values (1);"
СоветКак увидеть ход prepare

По умолчанию sqlrs оставляет на экране только самое необходимое. Глобальный флаг -v или --verbose сохраняет промежуточные сообщения и печатает больше деталей: например, sqlrs --verbose prepare:psql ….

Ожидаемый вывод
DSN=postgres://…

Всё после DSN= — строка подключения нового экземпляра: адрес, порт, имя базы и учётные данные. Конкретное значение меняется от запуска к запуску; не сохраняйте его в репозитории. Префикс нужен, чтобы shell-скрипт мог отделить значение от имени переменной.

Часть после -- — аргументы psql. sqlrs учитывает команду, образ и входные файлы при идентификации состояния. Само состояние не меняется, а выданный по DSN экземпляр предназначен для изменений.

Посмотрите, что получилось

sqlrs ls --states
sqlrs ls --instances
СоветПолный ID обычно не нужен

Для состояния или экземпляра достаточно однозначного шестнадцатеричного (hex) префикса длиной от восьми символов. В обычных таблицах sqlrs показывает первые 12 символов; флаг --long раскрывает ID полностью. ID фоновой задачи (job), в отличие от них, указывается целиком.

Схема таблицы состояний
STATE_ID      IMAGE_ID               KIND  PREPARE_ARGS  CREATED  SIZE  REFCOUNT
a1b2c3d4e5f6  postgres@0123456789ab  psql  …             …        …     1

STATE_ID идентифицирует неизменяемое состояние, IMAGE_ID — разрешённый образ базы, KIND — способ подготовки, а PREPARE_ARGS — нормализованный рецепт. REFCOUNT показывает, сколько экземпляров ссылаются на состояние. ID, время и размер в примере условные.

Схема таблицы экземпляров
INSTANCE_ID   IMAGE_ID               STATE_ID      NAME  CREATED  EXPIRES  STATUS
f6e5d4c3b2a1  postgres@0123456789ab  a1b2c3d4e5f6        …        …        active

INSTANCE_ID нужен для последующих run и rm. По STATE_ID видно, из какого состояния создан экземпляр; NAME пуст для экземпляра без имени, а STATUS показывает, можно ли им пользоваться.

В первой таблице будет состояние, во второй — созданный на его основе экземпляр. Запустите ту же prepare-команду ещё раз и снова выполните sqlrs ls --instances. Рецепт не изменился, поэтому sqlrs сможет переиспользовать подготовленное состояние, но выдаст новый изменяемый экземпляр. Изменения в одном экземпляре не попадут в другой.

Перенесите настоящий рецепт проекта

Однострочный SQL нужен только для знакомства. Реальные рецепты обычно используют:

  • prepare:psql — SQL-файлы, команды psql и цепочки \i/\ir;
  • prepare:lb — корневой Liquibase changelog и все подключаемые им файлы.

Сначала добейтесь успешного прямого вызова, например sqlrs prepare:psql -- -f db/prepare.sql. Затем сохраните громоздкую команду как репозиторный alias — именованный рецепт, который можно проверять и версионировать вместе с миграциями:

sqlrs alias create test-db prepare:psql -- -f db/prepare.sql
sqlrs prepare test-db
СоветПроверка и список псевдонимов

Проверить корректность псевдонима можно командой sqlrs alias check.

Посмотреть, какие псевдонимы есть в текущей рабочей области, можно командой sqlrs alias ls.

Команда создаст test-db.prep.s9s.yaml. Этот файл нужно коммитить; локальную папку .sqlrs/ — обычно нет. Если вы ещё не знаете, где в проекте находятся подходящие SQL, changelog или настройки, выполните sqlrs discover. Команда только анализирует файлы и предлагает следующие действия: она не создаёт рецепты, не меняет конфигурацию и не запускает миграции.

Выберите время жизни экземпляра

Для короткой SQL-проверки объедините prepare и run в одну команду. После завершения psql sqlrs сразу удалит временный экземпляр:

sqlrs prepare test-db run:psql -- -f tests/db-smoke.sql

Для серии проверок или отладки сначала создайте экземпляр, найдите его id, а затем запускайте команды отдельно. Запущенный отдельно run использует существующий экземпляр и не удаляет его после завершения:

sqlrs prepare test-db
sqlrs ls --instances
sqlrs run:psql --instance INSTANCE_ID -- -f tests/db-smoke.sql

В v0.2.0-rc.1 встроены режимы run для psql и pgbench. Произвольное приложение или обычную систему тестов запускайте привычной командой, передав ей DSN из стандартного вывода prepare через переменную окружения. Подробные примеры для PowerShell и POSIX-совместимой оболочки есть в разделе об автотестах.

Удалите то, что больше не нужно

Экземпляр — изменяемый лист дерева, созданный на основе состояния. У состояния могут быть не только экземпляры, но и дочерние состояния, если один prepare продолжает другой. Без --recurse состояние с любыми потомками заблокировано; с этим флагом sqlrs рассматривает всё поддерево и либо удаляет его целиком, либо не удаляет ничего, если хотя бы один потомок заблокирован.

sqlrs rm INSTANCE_ID_PREFIX
sqlrs rm --recurse STATE_ID_PREFIX
СоветСначала dry-run, затем удаление

Не используйте --recurse и --force без необходимости. Сначала выполните sqlrs rm --dry-run --recurse STATE_ID_PREFIX и проверьте всё дерево. --force разрешает удалить экземпляр с активными подключениями или уже начатую фоновую задачу (job), но сам по себе не включает рекурсивное удаление.

Вывод rm --dry-run --recurse
state a1b2c3d4e5f6 would delete
` instance f6e5d4c3b2a1 would delete (connections=0)

Дерево показывает корневое состояние и всех затронутых потомков. Для экземпляра также выводится число активных подключений. Значение would delete означает, что объект будет удалён при том же вызове без --dry-run; blocked объяснит, что мешает операции.

Различайте два уровня конфигурации

Файл .sqlrs/config.yaml относится к рабочей области: в нём находятся профиль, расположение движка, образ БД и параметры локального запуска. Команда sqlrs configобращается к конфигурации выбранного движка. Например, так можно посмотреть фактически выбранный способ снимков, временно включить copy и затем вернуть автоматический выбор:

sqlrs config get snapshot.backend --effective
sqlrs config set snapshot.backend "copy"
sqlrs config set snapshot.backend "auto"
СоветПроверяйте схему перед config set

Значения для config set задаются в формате JSON и проверяются схемой движка. Перед изменением незнакомого параметра выполните sqlrs config schema и сохраните исходное значение.

Вывод config get --effective
"auto"

Команда печатает эффективное JSON-значение после применения настроек и значений по умолчанию. Поэтому строка заключена в кавычки; числа, boolean, массивы и объекты выводятся в своих JSON-формах.

Куда двигаться дальше

Теперь у вас есть модель sqlrs и первый рабочий цикл. Остальные главы превращают его в повторяемый процесс для реального проекта:

  1. 01

    Подготовьте проект и окружение

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

  2. 02

    Выберите источник состояния

    Превратите SQL-, psql- или Liquibase-сценарий проекта в воспроизводимый рецепт подготовки.

  3. 03

    Проверьте проект командой discovery

    Получите подсказки о структуре проекта и проверьте каждое предложение перед применением.

  4. 04

    Подключите существующие автотесты

    Передайте тестам DSN воспроизводимого экземпляра и сохраните привычный способ запуска.

  5. 05

    Анализируйте миграции между ревизиями

    Сравнивайте файловые входы и поднимайте состояния из коммитов и тегов с учётом ограничений diff.

  6. 06

    Разберите типовые проблемы

    Начните с безопасных проверок рабочей области, окружения, рецептов, кэша и Git-контекста.

Границы учебника

Команды проверены по интерфейсу релиз-кандидата v0.2.0-rc.1. Нативная подготовка покрывает psql и Liquibase. Для Flyway, ORM-миграций и собственного инструмента миграций ниже показан переходный путь через воспроизводимый SQL. Командная версия готовится к закрытой бете, облачная доступна только участникам закрытой альфы по приглашению; все практические примеры этого учебника относятся к локальной версии.

Подготовьте рабочий проект

Проверьте требования своей платформы и создайте рабочую область в корне репозитория.

Перейти к настройке