Dbmate — это инструмент миграции базы данных, который будет синхронизировать схему вашей базы данных между несколькими разработчиками и вашими производственными серверами.
Это автономный инструмент командной строки, который можно использовать с Go, Node.js, Python, Ruby, PHP, Rust, C++ или любым другим языком или платформой, которую вы используете для написания приложений на основе базы данных. Это особенно полезно, если вы пишете несколько сервисов на разных языках и хотите сохранить здравомыслие с помощью согласованных инструментов разработки.
Для сравнения dbmate и других популярных инструментов миграции схемы базы данных см. Альтернативы.
schema.sql
, чтобы легко различать изменения схемы в git.DATABASE_URL
) или указывается в командной строке..env
НПМ
Установите с помощью NPM:
npm install --save-dev dbmate
npx dbmate --help
macOS
Установите с помощью Homebrew:
brew install dbmate
dbmate --help
Линукс
Установите двоичный файл напрямую:
sudo curl -fsSL -o /usr/local/bin/dbmate https://github.com/amacneil/dbmate/releases/latest/download/dbmate-linux-amd64
sudo chmod +x /usr/local/bin/dbmate
/usr/local/bin/dbmate --help
Окна
Установить с помощью Scoop
scoop install dbmate
dbmate -- help
Докер
Образы Docker публикуются в реестре контейнеров GitHub ( ghcr.io/amacneil/dbmate
).
Не забудьте установить --network=host
или посмотрите этот комментарий, чтобы получить дополнительные советы по использованию dbmate с сетью Docker):
docker run --rm -it --network=host ghcr.io/amacneil/dbmate --help
Если вы хотите создать или применить миграцию, вам нужно будет использовать функцию монтирования привязки Docker, чтобы сделать ваш локальный рабочий каталог ( pwd
) доступным внутри контейнера dbmate:
docker run --rm -it --network=host -v " $( pwd ) /db:/db " ghcr.io/amacneil/dbmate new create_users_table
dbmate --help # print usage help
dbmate new # generate a new migration file
dbmate up # create the database (if it does not already exist) and run any pending migrations
dbmate create # create the database
dbmate drop # drop the database
dbmate migrate # run any pending migrations
dbmate rollback # roll back the most recent migration
dbmate down # alias for rollback
dbmate status # show the status of all migrations (supports --exit-code and --quiet)
dbmate dump # write the database schema.sql file
dbmate load # load schema.sql file to the database
dbmate wait # wait for the database server to become available
Следующие параметры доступны для всех команд. Вы должны использовать аргументы командной строки в следующем порядке: dbmate [global options] command [command options]
. Большинство параметров также можно настроить с помощью переменных среды (и загрузить из вашего файла .env
, что полезно для обмена конфигурацией между членами команды).
--url, -u "protocol://host:port/dbname"
— напрямую указать URL базы данных. (окр: DATABASE_URL
)--env, -e "DATABASE_URL"
— указать переменную среды, из которой будет считываться URL-адрес подключения к базе данных.--env-file ".env"
— укажите альтернативные файлы переменных среды для загрузки.--migrations-dir, -d "./db/migrations"
— где хранить файлы миграции. (окр: DBMATE_MIGRATIONS_DIR
)--migrations-table "schema_migrations"
— таблица базы данных для записи миграций (env: DBMATE_MIGRATIONS_TABLE
)--schema-file, -s "./db/schema.sql"
— путь для хранения файла Schema.sql. (окр.: DBMATE_SCHEMA_FILE
)--no-dump-schema
— не обновлять автоматически файл Schema.sql при миграции/откате (env: DBMATE_NO_DUMP_SCHEMA
)--strict
— сбой, если миграции будут применяться не по порядку (env: DBMATE_STRICT
)--wait
— дождаться, пока база данных станет доступной, прежде чем выполнять следующую команду (env: DBMATE_WAIT
)--wait-timeout 60s
— таймаут для флага --wait (env: DBMATE_WAIT_TIMEOUT
) Dbmate находит вашу базу данных, используя переменную среды DATABASE_URL
по умолчанию. Если вы пишете двенадцатифакторное приложение, вам следует хранить все строки подключения в переменных среды.
Чтобы упростить разработку, dbmate ищет файл .env
в текущем каталоге и обрабатывает все перечисленные там переменные так, как если бы они были указаны в текущей среде (однако существующие переменные среды имеют преимущество).
Если у вас еще нет файла .env
, создайте его и добавьте URL-адрес подключения к базе данных:
$ cat .env
DATABASE_URL= " postgres://[email protected]:5432/myapp_development?sslmode=disable "
DATABASE_URL
следует указывать в следующем формате:
protocol://username:password@host:port/database_name?options
protocol
должен быть одним из mysql
, postgres
, postgresql
, sqlite
, sqlite3
, clickhouse
username
и password
должны быть закодированы в URL (при использовании специальных символов вы получите сообщение об ошибке)host
может быть либо именем хоста, либо IP-адресомoptions
зависят от драйвера (если вы хотите их использовать, обратитесь к базовым драйверам Go SQL) Dbmate также может загрузить URL-адрес соединения из другой переменной среды. Например, перед запуском набора тестов вы можете удалить и заново создать тестовую базу данных. Один из простых способов сделать это — сохранить URL-адрес подключения к тестовой базе данных в переменной среды TEST_DATABASE_URL
:
$ cat .env
DATABASE_URL= " postgres://[email protected]:5432/myapp_dev?sslmode=disable "
TEST_DATABASE_URL= " postgres://[email protected]:5432/myapp_test?sslmode=disable "
Затем вы можете указать эту переменную среды в своем тестовом сценарии (Makefile или аналогичном):
$ dbmate -e TEST_DATABASE_URL drop
Dropping: myapp_test
$ dbmate -e TEST_DATABASE_URL --no-dump-schema up
Creating: myapp_test
Applying: 20151127184807_create_users_table.sql
Applied: 20151127184807_create_users_table.sql in 123µs
Альтернативно вы можете указать URL-адрес непосредственно в командной строке:
$ dbmate -u " postgres://[email protected]:5432/myapp_test?sslmode=disable " up
Единственное преимущество использования dbmate -e TEST_DATABASE_URL
перед dbmate -u $TEST_DATABASE_URL
заключается в том, что первый вариант использует автоматическую загрузку файла .env
dbmate.
При подключении к Postgres вам может потребоваться добавить параметр sslmode=disable
в строку подключения, поскольку dbmate по умолчанию требует соединения TLS (некоторые другие платформы/языки по умолчанию допускают незашифрованные соединения).
DATABASE_URL= " postgres://username:[email protected]:5432/database_name?sslmode=disable "
Для подключения через сокет unix можно указать параметр socket
или host
(примечание: укажите только каталог):
DATABASE_URL= " postgres://username:password@/database_name?socket=/var/run/postgresql "
Параметр search_path
можно использовать для указания текущей схемы при применении миграции, а также для таблицы schema_migrations
в dbmate. Если схема не существует, она будет создана автоматически. Если передано несколько схем, разделенных запятыми, первая будет использоваться для таблицы schema_migrations
.
DATABASE_URL= " postgres://username:[email protected]:5432/database_name?search_path=myschema "
DATABASE_URL= " postgres://username:[email protected]:5432/database_name?search_path=myschema,public "
DATABASE_URL= " mysql://username:[email protected]:3306/database_name "
Параметр socket
может быть указан для подключения через сокет unix:
DATABASE_URL= " mysql://username:password@/database_name?socket=/var/run/mysqld/mysqld.sock "
Базы данных SQLite хранятся в файловой системе, поэтому вам не нужно указывать хост. По умолчанию файлы располагаются относительно текущего каталога. Например, следующая команда создаст базу данных по адресу ./db/database.sqlite3
:
DATABASE_URL= " sqlite:db/database.sqlite3 "
Чтобы указать абсолютный путь, добавьте к пути косую черту. Следующее создаст базу данных в /tmp/database.sqlite3
:
DATABASE_URL= " sqlite:/tmp/database.sqlite3 "
DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name "
Для работы с кластером ClickHouse можно указать 4 параметра запроса на подключение:
on_cluster
— указание на использование операторов кластера и реплицируемой таблицы миграции. (по умолчанию: false
). Если этот параметр не указан, другие параметры запроса, связанные с кластером, игнорируются. DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster "
DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster=true "
cluster_macro
(Необязательно) — значение макроса, которое будет использоваться для операторов ON CLUSTER и для пути Zookeeper механизма реплицируемой таблицы миграции. (по умолчанию: {cluster}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&cluster_macro={my_cluster} "
replica_macro
(Необязательно) — значение макроса, которое будет использоваться для имени реплики в механизме таблицы реплицируемой миграции. (по умолчанию: {replica}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&replica_macro={my_replica} "
zoo_path
(Необязательно) — Путь к миграции таблицы в ClickHouse/Zoo Keeper. (по умолчанию: /clickhouse/tables/<cluster_macro>/{table}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&zoo_path=/zk/path/tables "
См. другие поддерживаемые варианты подключения.
Следуйте следующему формату DATABASE_URL
при подключении к фактическому BigQuery в GCP:
bigquery://projectid/location/dataset
projectid
(обязательный) - ID проекта
dataset
(обязательно) — название набора данных в рамках проекта.
location
(необязательно) — место создания набора данных.
ПРИМЕЧАНИЕ. Следуйте этому документу, чтобы узнать, как установить переменную среды GOOGLE_APPLICATION_CREDENTIALS
для правильной аутентификации.
Если вы пытаетесь подключиться к пользовательской конечной точке, например к эмулятору BigQuery, следуйте следующему формату.
bigquery://host:port/projectid/location/dataset?disable_auth=true
disable_auth
(необязательно) — укажите true
, чтобы пропустить аутентификацию, используйте только для тестирования и подключения к эмулятору.
Поддержка Spanner в настоящее время ограничена базами данных, использующими диалект PostgreSQL, который необходимо выбрать при создании базы данных. Информацию о будущем Spanner с поддержкой GoogleSQL см. в этом обсуждении.
Spanner с интерфейсом Postgres требует, чтобы PGAdapter был запущен. Используйте следующий формат для DATABASE_URL
с указанием хоста и порта, на котором работает PGAdapter:
DATABASE_URL= " spanner-postgres://127.0.0.1:5432/database_name?sslmode=disable "
Обратите внимание, что указывать имя пользователя и пароль не обязательно, поскольку аутентификация осуществляется PGAdapter (они будут игнорироваться PGAdapter, если они указаны).
Поддерживаются другие параметры драйвера postgres.
Spanner также не позволяет выполнять DDL внутри явных транзакций. Поэтому вы должны указать transaction:false
для миграций, включающих DDL:
-- migrate:up transaction:false
CREATE TABLE ...
-- migrate:down transaction:false
DROP TABLE ...
Дампы схемы в настоящее время не поддерживаются, поскольку pg_dump
использует функции, не предоставляемые Spanner.
Чтобы создать новую миграцию, запустите dbmate new create_users_table
. Вы можете назвать миграцию как угодно. Это создаст файл db/migrations/20151127184807_create_users_table.sql
в текущем каталоге:
-- migrate:up
-- migrate:down
Чтобы написать миграцию, просто добавьте свой SQL в разделmigrate migrate:up
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
Примечание. Файлы миграции имеют имена в формате
[version]_[description].sql
. В базе данных записывается только версия (определяемая как все начальные цифры в имени файла), поэтому вы можете безопасно переименовать файл миграции, не оказывая никакого влияния на его текущее состояние приложения.
Запустите dbmate up
чтобы выполнить любые ожидающие миграции.
$ dbmate up
Creating: myapp_development
Applying: 20151127184807_create_users_table.sql
Applied: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
Примечание.
dbmate up
создаст базу данных, если она еще не существует (при условии, что текущий пользователь имеет разрешение на создание баз данных). Если вы хотите выполнить миграцию без создания базы данных, запуститеdbmate migrate
.
Ожидающие миграции всегда применяются в числовом порядке. Однако dbmate не предотвращает неупорядоченное применение миграций, если они фиксируются независимо (например: если разработчик работает над веткой в течение длительного времени и фиксирует миграцию, которая имеет более низкий номер версии, чем другие уже существующие миграции). примененные миграции, dbmate просто применит ожидающую миграцию). См. № 159 для более подробного объяснения.
По умолчанию dbmate не знает, как отменить миграцию. При разработке часто бывает полезно иметь возможность вернуть базу данных в предыдущее состояние. Для этого реализуйте migrate:down
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
drop table users;
Запустите dbmate rollback
, чтобы откатить самую последнюю миграцию:
$ dbmate rollback
Rolling back: 20151127184807_create_users_table.sql
Rolled back: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
dbmate поддерживает параметры, передаваемые в блок миграции в форме пар key:value
. Список поддерживаемых опций:
transaction
сделка
transaction
полезна, если вы не хотите запускать SQL внутри транзакции:
-- migrate:up transaction:false
ALTER TYPE colors ADD VALUE ' orange ' AFTER ' red ' ;
transaction
по умолчанию будет иметь значение true
если ваша база данных поддерживает ее.
Если вы используете среду разработки Docker для своего проекта, вы можете столкнуться с проблемами, связанными с тем, что база данных не готова сразу при выполнении миграций или модульных тестов. Это может быть связано с тем, что сервер базы данных только что запустился.
В общем, ваше приложение должно быть устойчивым к отсутствию рабочего соединения с базой данных при запуске. Однако для выполнения миграций или модульных тестов это непрактично. Команда wait
позволяет избежать этой ситуации, позволяя приостановить выполнение сценария или другого приложения до тех пор, пока база данных не станет доступной. Dbmate будет пытаться подключиться к серверу базы данных каждую секунду, максимум до 60 секунд.
Если база данных доступна, wait
не вернет никаких результатов:
$ dbmate wait
Если база данных недоступна, wait
будет заблокирована, пока база данных не станет доступной:
$ dbmate wait
Waiting for database....
Вы также можете использовать флаг --wait
с другими командами, если вы иногда видите сбои, вызванные тем, что база данных еще не готова:
$ dbmate --wait up
Waiting for database....
Creating: myapp_development
Вы можете настроить тайм-аут, используя --wait-timeout
(по умолчанию 60 с). Если база данных по-прежнему недоступна, команда вернет ошибку:
$ dbmate --wait-timeout=5s wait
Waiting for database.....
Error: unable to connect to database: dial tcp 127.0.0.1:5432: connect: connection refused
Обратите внимание, что команда wait
не проверяет, существует ли указанная вами база данных, а проверяет только то, что сервер доступен и готов (поэтому она вернет успех, если сервер базы данных доступен, но ваша база данных еще не создана).
Когда вы запускаете команды up
, migrate
rollback
, dbmate автоматически создаст файл ./db/schema.sql
, содержащий полное представление схемы вашей базы данных. Dbmate поддерживает актуальность этого файла, поэтому вам не придется редактировать его вручную.
Рекомендуется проверить этот файл в системе контроля версий, чтобы можно было легко просматривать изменения в схеме в коммитах или запросах на включение. Этот файл также можно использовать, если вы хотите быстро загрузить схему базы данных, не запуская каждую миграцию последовательно (например, в вашей тестовой программе). Однако, если вы не хотите сохранять этот файл, вы можете добавить его в свой .gitignore
или указать параметр командной строки --no-dump-schema
.
Чтобы создать дамп файла schema.sql
, не выполняя никаких других действий, запустите dbmate dump
. В отличие от других действий dbmate, эта команда использует соответствующие команды pg_dump
, mysqldump
или sqlite3
, доступные в вашем PATH. Если эти инструменты недоступны, dbmate автоматически пропустит шаг дампа схемы во время действий up
, migrate
или rollback
. Вы можете диагностировать проблему, запустив dbmate dump
и просмотрев выходные данные:
$ dbmate dump
exec: " pg_dump " : executable file not found in $PATH
В системах Ubuntu или Debian это можно исправить, установив postgresql-client
, mysql-client
или sqlite3
соответственно. Убедитесь, что версия устанавливаемого вами пакета больше или равна версии, работающей на вашем сервере базы данных.
Примечание. Файл
schema.sql
будет содержать полную схему вашей базы данных, даже если некоторые таблицы или столбцы были созданы вне миграции dbmate.
Dbmate предназначен для использования в качестве CLI с любым языком или платформой, но его также можно использовать в качестве библиотеки в приложении Go.
Вот простой пример. Не забудьте импортировать нужный вам драйвер!
package main
import (
"net/url"
"github.com/amacneil/dbmate/v2/pkg/dbmate"
_ "github.com/amacneil/dbmate/v2/pkg/driver/sqlite"
)
func main () {
u , _ := url . Parse ( "sqlite:foo.sqlite3" )
db := dbmate . New ( u )
err := db . CreateAndMigrate ()
if err != nil {
panic ( err )
}
}
Дополнительные параметры см. в справочной документации.
Миграции можно встроить в двоичный файл вашего приложения с помощью функции встраивания Go.
Используйте db.FS
, чтобы указать файловую систему, используемую для чтения миграций:
package main
import (
"embed"
"fmt"
"net/url"
"github.com/amacneil/dbmate/v2/pkg/dbmate"
_ "github.com/amacneil/dbmate/v2/pkg/driver/sqlite"
)
//go:embed db/migrations/*.sql
var fs embed. FS
func main () {
u , _ := url . Parse ( "sqlite:foo.sqlite3" )
db := dbmate . New ( u )
db . FS = fs
fmt . Println ( "Migrations:" )
migrations , err := db . FindMigrations ()
if err != nil {
panic ( err )
}
for _ , m := range migrations {
fmt . Println ( m . Version , m . FilePath )
}
fmt . Println ( " n Applying..." )
err = db . CreateAndMigrate ()
if err != nil {
panic ( err )
}
}
Файлы миграции очень просты и по умолчанию хранятся в папке ./db/migrations
. Вы можете создать новый файл миграции с именем [date]_create_users.sql
, запустив dbmate new create_users
. Вот пример:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
);
-- migrate:down
drop table if exists users;
Миграции вверх и вниз хранятся в одном файле для удобства редактирования. Директивы up и down обязательны, даже если вы решите не реализовывать нисходящую миграцию.
Когда вы применяете миграцию, dbmate сохраняет только номер версии, а не содержимое, поэтому вам всегда следует откатывать миграцию перед изменением ее содержимого. По этой причине вы можете безопасно переименовать файл миграции, не затрагивая его примененный статус, пока вы сохраняете номер версии.
По умолчанию файл схемы записывается в ./db/schema.sql
. Это полный дамп схемы вашей базы данных, включая все примененные миграции и любые другие внесенные вами изменения.
Этот файл следует вернуть в систему контроля версий, чтобы вы могли легко сравнить различия миграции. Вы можете использовать файл схемы для быстрого восстановления базы данных без необходимости выполнения всех миграций.
Dbmate хранит записи о каждой примененной миграции в таблице с именем schema_migrations
. Эта таблица будет создана автоматически, если она еще не существует.
Таблица очень простая:
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR ( 255 ) PRIMARY KEY
)
Вы можете настроить имя этой таблицы, используя флаг --migrations-table
или переменную среды DBMATE_MIGRATIONS_TABLE
.
Зачем нужен еще один инструмент миграции схемы базы данных? Dbmate был вдохновлен многими другими инструментами, в первую очередь Active Record Migrations, с целью сделать его простым в настройке и независимым от языка и платформы. Вот сравнение dbmate и других популярных инструментов миграции.
dbmate | Гусь | sql-миграция | голанг-мигрировать | активная запись | продолжить | пролетный путь | скитч | |
---|---|---|---|---|---|---|---|---|
Функции | ||||||||
Простые файлы миграции SQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
Поддержка создания и удаления баз данных. | ✅ | ✅ | ||||||
Поддержка сохранения файлов дампа схемы. | ✅ | ✅ | ||||||
Файлы миграции с указанием временной метки | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Таблица миграции пользовательских схем | ✅ | ✅ | ✅ | ✅ | ||||
Возможность дождаться готовности базы данных | ✅ | |||||||
Строка подключения к базе данных, загруженная из переменных среды | ✅ | ✅ | ||||||
Автоматически загружать файл .env | ✅ | |||||||
Нет отдельного файла конфигурации | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Независимый от языка/фреймворка | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Драйверы | ||||||||
PostgreSQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
MySQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
SQLite | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
ClickHouse | ✅ | ✅ | ✅ | ✅ |
Если вы заметили какие-либо неточности в этой таблице, пожалуйста, предложите изменение.
Dbmate написан на Go, запросы на включение приветствуются.
Тесты выполняются на реальной базе данных с использованием Docker Compose. Чтобы создать образ Docker и запустить тесты:
$ make docker-all
Чтобы запустить оболочку разработки:
$ make docker-sh