Dbmate es una herramienta de migración de bases de datos que mantendrá sincronizado el esquema de su base de datos entre múltiples desarrolladores y sus servidores de producción.
Es una herramienta de línea de comandos independiente que se puede usar con Go, Node.js, Python, Ruby, PHP, Rust, C++ o cualquier otro lenguaje o marco que esté utilizando para escribir aplicaciones respaldadas por bases de datos. Esto es especialmente útil si está escribiendo múltiples servicios en diferentes idiomas y desea mantener cierta cordura con herramientas de desarrollo consistentes.
Para obtener una comparación entre dbmate y otras herramientas populares de migración de esquemas de bases de datos, consulte Alternativas.
schema.sql
para diferenciar fácilmente los cambios de esquema en gitDATABASE_URL
de forma predeterminada) o se especifica en la línea de comando.env
MNP
Instalar usando NPM:
npm install --save-dev dbmate
npx dbmate --help
macos
Instalar usando Homebrew:
brew install dbmate
dbmate --help
linux
Instale el binario directamente:
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
ventanas
Instalar usando Scoop
scoop install dbmate
dbmate -- help
Estibador
Las imágenes de Docker se publican en GitHub Container Registry ( ghcr.io/amacneil/dbmate
).
Recuerde configurar --network=host
o ver este comentario para obtener más consejos sobre cómo usar dbmate con Docker Networking):
docker run --rm -it --network=host ghcr.io/amacneil/dbmate --help
Si desea crear o aplicar migraciones, deberá utilizar la función de montaje vinculado de Docker para que su directorio de trabajo local ( pwd
) esté disponible dentro del contenedor 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
Las siguientes opciones están disponibles con todos los comandos. Debe utilizar argumentos de línea de comando en el orden dbmate [global options] command [command options]
. La mayoría de las opciones también se pueden configurar mediante variables de entorno (y cargar desde su archivo .env
, lo cual es útil para compartir la configuración entre los miembros del equipo).
--url, -u "protocol://host:port/dbname"
- especifica la URL de la base de datos directamente. (entorno: DATABASE_URL
)--env, -e "DATABASE_URL"
: especifica una variable de entorno para leer la URL de conexión de la base de datos.--env-file ".env"
: especifica archivos de variables de entorno alternativos para cargar.--migrations-dir, -d "./db/migrations"
- dónde guardar los archivos de migración. (entorno: DBMATE_MIGRATIONS_DIR
)--migrations-table "schema_migrations"
- tabla de base de datos para registrar las migraciones. (env: DBMATE_MIGRATIONS_TABLE
)--schema-file, -s "./db/schema.sql"
- una ruta para guardar el archivo esquema.sql. (entorno: DBMATE_SCHEMA_FILE
)--no-dump-schema
: no actualiza automáticamente el archivo esquema.sql al migrar/revertir (env: DBMATE_NO_DUMP_SCHEMA
)--strict
: falla si las migraciones se aplicarían fuera de orden (entorno: DBMATE_STRICT
)--wait
: espera a que la base de datos esté disponible antes de ejecutar el comando siguiente (env: DBMATE_WAIT
)--wait-timeout 60s
- tiempo de espera para --wait bandera (env: DBMATE_WAIT_TIMEOUT
) Dbmate localiza su base de datos utilizando la variable de entorno DATABASE_URL
de forma predeterminada. Si está escribiendo una aplicación de doce factores, debería almacenar todas las cadenas de conexión en variables de entorno.
Para facilitar esto en el desarrollo, dbmate busca un archivo .env
en el directorio actual y trata cualquier variable enumerada allí como si estuviera especificada en el entorno actual (sin embargo, las variables de entorno existentes tienen preferencia).
Si aún no tiene un archivo .env
, cree uno y agregue la URL de conexión de su base de datos:
$ cat .env
DATABASE_URL= " postgres://[email protected]:5432/myapp_development?sslmode=disable "
DATABASE_URL
debe especificarse en el siguiente formato:
protocol://username:password@host:port/database_name?options
protocol
debe ser uno de mysql
, postgres
, postgresql
, sqlite
, sqlite3
, clickhouse
username
y password
deben estar codificados en URL (obtendrá un error si utiliza caracteres especiales).host
puede ser un nombre de host o una dirección IP.options
son específicas del controlador (consulte los controladores Go SQL subyacentes si desea utilizarlos) Dbmate también puede cargar la URL de conexión desde una variable de entorno diferente. Por ejemplo, antes de ejecutar su conjunto de pruebas, es posible que desee eliminar y volver a crear la base de datos de prueba. Una forma sencilla de hacerlo es almacenar la URL de conexión de la base de datos de prueba en la variable de entorno 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 "
Luego puede especificar esta variable de entorno en su script de prueba (Makefile o similar):
$ 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
Alternativamente, puedes especificar la URL directamente en la línea de comando:
$ dbmate -u " postgres://[email protected]:5432/myapp_test?sslmode=disable " up
La única ventaja de usar dbmate -e TEST_DATABASE_URL
sobre dbmate -u $TEST_DATABASE_URL
es que el primero aprovecha la carga automática de archivos .env
de dbmate.
Al conectarse a Postgres, es posible que necesite agregar la opción sslmode=disable
a su cadena de conexión, ya que dbmate requiere de forma predeterminada una conexión TLS (algunos otros marcos/lenguajes permiten conexiones no cifradas de forma predeterminada).
DATABASE_URL= " postgres://username:[email protected]:5432/database_name?sslmode=disable "
Se puede especificar un socket
o parámetro host
para conectarse a través de un socket Unix (nota: especifique solo el directorio):
DATABASE_URL= " postgres://username:password@/database_name?socket=/var/run/postgresql "
Se puede utilizar un parámetro search_path
para especificar el esquema actual al aplicar las migraciones, así como para la tabla schema_migrations
de dbmate. Si el esquema no existe, se creará automáticamente. Si se pasan varios esquemas separados por comas, el primero se utilizará para la tabla 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 "
Se puede especificar un parámetro socket
para conectarse a través de un socket Unix:
DATABASE_URL= " mysql://username:password@/database_name?socket=/var/run/mysqld/mysqld.sock "
Las bases de datos SQLite se almacenan en el sistema de archivos, por lo que no es necesario especificar un host. De forma predeterminada, los archivos son relativos al directorio actual. Por ejemplo, lo siguiente creará una base de datos en ./db/database.sqlite3
:
DATABASE_URL= " sqlite:db/database.sqlite3 "
Para especificar una ruta absoluta, agregue una barra diagonal a la ruta. Lo siguiente creará una base de datos en /tmp/database.sqlite3
:
DATABASE_URL= " sqlite:/tmp/database.sqlite3 "
DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name "
Para trabajar con el clúster ClickHouse, se pueden proporcionar cuatro parámetros de consulta de conexión:
on_cluster
: indicación para utilizar declaraciones de clúster y tabla de migración replicada. (predeterminado: false
) Si no se proporciona este parámetro, se ignoran otros parámetros de consulta relacionados con el clúster. 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
(opcional): valor de macro que se utilizará para las declaraciones ON CLUSTER y para la ruta del cuidador del zoológico del motor de tabla de migración replicada. (predeterminado: {cluster}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&cluster_macro={my_cluster} "
replica_macro
(opcional): valor de macro que se utilizará para el nombre de la réplica en el motor de la tabla de migración replicada. (predeterminado: {replica}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&replica_macro={my_replica} "
zoo_path
(opcional): la ruta a la migración de la tabla en ClickHouse/Zoo Keeper. (predeterminado: /clickhouse/tables/<cluster_macro>/{table}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&zoo_path=/zk/path/tables "
Vea otras opciones de conexión admitidas.
Siga el siguiente formato para DATABASE_URL
cuando se conecte a BigQuery real en GCP:
bigquery://projectid/location/dataset
projectid
(obligatorio) - ID del proyecto
dataset
(obligatorio): nombre del conjunto de datos dentro del proyecto
location
(opcional): donde se crea el conjunto de datos.
NOTA: Siga este documento sobre cómo configurar la variable de entorno GOOGLE_APPLICATION_CREDENTIALS
para una autenticación adecuada
Siga el siguiente formato si intenta conectarse a un punto final personalizado, por ejemplo, BigQuery Emulator.
bigquery://host:port/projectid/location/dataset?disable_auth=true
disable_auth
(opcional): pase true
para omitir la autenticación, utilícelo solo para probar y conectarse al emulador.
Actualmente, la compatibilidad con Spanner está limitada a bases de datos que utilizan el dialecto PostgreSQL, que debe elegirse durante la creación de la base de datos. Para el futuro Spanner con soporte de GoogleSQL, consulte esta discusión.
Spanner con la interfaz Postgres requiere que PGAdapter esté ejecutándose. Utilice el siguiente formato para DATABASE_URL
, con el host y el puerto configurados en donde se ejecuta PGAdapter:
DATABASE_URL= " spanner-postgres://127.0.0.1:5432/database_name?sslmode=disable "
Tenga en cuenta que no es necesario especificar un nombre de usuario y contraseña, ya que PGAdapter maneja la autenticación (el PGAdapter los ignorará si se especifican).
Se admiten otras opciones del controlador postgres.
Spanner tampoco permite que se ejecute DDL dentro de transacciones explícitas. Por lo tanto, debe especificar transaction:false
en migraciones que incluyan DDL:
-- migrate:up transaction:false
CREATE TABLE ...
-- migrate:down transaction:false
DROP TABLE ...
Actualmente no se admiten volcados de esquemas, ya que pg_dump
utiliza funciones que Spanner no proporciona.
Para crear una nueva migración, ejecute dbmate new create_users_table
. Puedes nombrar la migración como quieras. Esto creará un archivo db/migrations/20151127184807_create_users_table.sql
en el directorio actual:
-- migrate:up
-- migrate:down
Para escribir una migración, simplemente agregue su SQL a la sección migrate:up
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
Nota: Los nombres de los archivos de migración tienen el formato
[version]_[description].sql
. Sólo la versión (definida como todos los caracteres numéricos iniciales en el nombre del archivo) se registra en la base de datos, por lo que puede cambiar el nombre de un archivo de migración de forma segura sin tener ningún efecto en el estado actual de la aplicación.
Ejecute dbmate up
para ejecutar cualquier migraciones pendientes.
$ dbmate up
Creating: myapp_development
Applying: 20151127184807_create_users_table.sql
Applied: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
Nota:
dbmate up
creará la base de datos si aún no existe (suponiendo que el usuario actual tenga permiso para crear bases de datos). Si desea ejecutar migraciones sin crear la base de datos, ejecutedbmate migrate
.
Las migraciones pendientes siempre se aplican en orden numérico. Sin embargo, dbmate no evita que las migraciones se apliquen fuera de orden si se confirman de forma independiente (por ejemplo: si un desarrollador ha estado trabajando en una rama durante mucho tiempo y confirma una migración que tiene un número de versión más bajo que otras ya). migraciones aplicadas, dbmate simplemente aplicará la migración pendiente). Consulte el n.° 159 para obtener una explicación más detallada.
De forma predeterminada, dbmate no sabe cómo revertir una migración. Durante el desarrollo, suele resultar útil poder revertir la base de datos a un estado anterior. Para lograr esto, implemente la sección migrate:down
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
drop table users;
Ejecute dbmate rollback
para revertir la migración más reciente:
$ dbmate rollback
Rolling back: 20151127184807_create_users_table.sql
Rolled back: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
dbmate admite opciones pasadas a un bloque de migración en forma de pares key:value
. Lista de opciones admitidas:
transaction
transacción
transaction
es útil si no desea ejecutar SQL dentro de una transacción:
-- migrate:up transaction:false
ALTER TYPE colors ADD VALUE ' orange ' AFTER ' red ' ;
transaction
será true
de forma predeterminada si su base de datos lo admite.
Si utiliza un entorno de desarrollo Docker para su proyecto, puede encontrar problemas con la base de datos que no esté lista inmediatamente al ejecutar migraciones o pruebas unitarias. Esto puede deberse a que el servidor de la base de datos acaba de iniciarse.
En general, su aplicación debe ser resistente a no tener una conexión de base de datos que funcione al inicio. Sin embargo, para ejecutar migraciones o pruebas unitarias, esto no es práctico. El comando wait
evita esta situación al permitirle pausar un script u otra aplicación hasta que la base de datos esté disponible. Dbmate intentará conectarse al servidor de la base de datos cada segundo, hasta un máximo de 60 segundos.
Si la base de datos está disponible, wait
no devolverá ningún resultado:
$ dbmate wait
Si la base de datos no está disponible, wait
se bloqueará hasta que la base de datos esté disponible:
$ dbmate wait
Waiting for database....
También puede usar el indicador --wait
con otros comandos si a veces ve fallas causadas porque la base de datos aún no está lista:
$ dbmate --wait up
Waiting for database....
Creating: myapp_development
Puede personalizar el tiempo de espera usando --wait-timeout
(60 segundos por defecto). Si la base de datos aún no está disponible, el comando devolverá un error:
$ dbmate --wait-timeout=5s wait
Waiting for database.....
Error: unable to connect to database: dial tcp 127.0.0.1:5432: connect: connection refused
Tenga en cuenta que el comando wait
no verifica si la base de datos especificada existe, solo que el servidor está disponible y listo (por lo que devolverá el éxito si el servidor de la base de datos está disponible, pero su base de datos aún no se ha creado).
Cuando ejecuta los comandos up
, migrate
o rollback
, dbmate creará automáticamente un archivo ./db/schema.sql
que contiene una representación completa del esquema de su base de datos. Dbmate mantiene este archivo actualizado para usted, por lo que no debe editarlo manualmente.
Se recomienda registrar este archivo en el control de código fuente, para que pueda revisar fácilmente los cambios en el esquema en confirmaciones o solicitudes de extracción. También es posible utilizar este archivo cuando desee cargar rápidamente un esquema de base de datos, sin ejecutar cada migración de forma secuencial (por ejemplo, en su equipo de prueba). Sin embargo, si no desea guardar este archivo, puede agregarlo a su .gitignore
o pasar la opción de línea de comando --no-dump-schema
.
Para volcar el archivo schema.sql
sin realizar ninguna otra acción, ejecute dbmate dump
. A diferencia de otras acciones de dbmate, este comando depende de que los respectivos comandos pg_dump
, mysqldump
o sqlite3
estén disponibles en su RUTA. Si estas herramientas no están disponibles, dbmate omitirá silenciosamente el paso de volcado del esquema durante las acciones de up
, migrate
o rollback
. Puede diagnosticar el problema ejecutando dbmate dump
y observando el resultado:
$ dbmate dump
exec: " pg_dump " : executable file not found in $PATH
En los sistemas Ubuntu o Debian, puedes solucionar este problema instalando postgresql-client
, mysql-client
o sqlite3
respectivamente. Asegúrese de que la versión del paquete que instale sea mayor o igual a la versión que se ejecuta en su servidor de base de datos.
Nota: El archivo
schema.sql
contendrá un esquema completo para su base de datos, incluso si algunas tablas o columnas se crearon fuera de las migraciones de dbmate.
Dbmate está diseñado para usarse como CLI con cualquier lenguaje o marco, pero también se puede usar como biblioteca en una aplicación Go.
He aquí un ejemplo sencillo. ¡Recuerde importar el controlador que necesita!
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 )
}
}
Consulte la documentación de referencia para obtener más opciones.
Las migraciones se pueden integrar en el binario de su aplicación utilizando la funcionalidad de inserción de Go.
Utilice db.FS
para especificar el sistema de archivos utilizado para leer las migraciones:
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 )
}
}
Los archivos de migración son muy simples y se almacenan en ./db/migrations
de forma predeterminada. Puede crear un nuevo archivo de migración llamado [date]_create_users.sql
ejecutando dbmate new create_users
. Aquí hay un ejemplo:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
);
-- migrate:down
drop table if exists users;
Tanto las migraciones ascendentes como las descendentes se almacenan en el mismo archivo para facilitar la edición. Se requieren directivas tanto hacia arriba como hacia abajo, incluso si decide no implementar la migración hacia abajo.
Cuando aplica una migración, dbmate solo almacena el número de versión, no el contenido, por lo que siempre debe revertir una migración antes de modificar su contenido. Por este motivo, puede cambiar el nombre de un archivo de migración de forma segura sin afectar su estado aplicado, siempre y cuando mantenga intacto el número de versión.
El archivo de esquema se escribe en ./db/schema.sql
de forma predeterminada. Es un volcado completo del esquema de su base de datos, incluidas las migraciones aplicadas y cualquier otra modificación que haya realizado.
Este archivo debe registrarse en el control de código fuente, para que pueda comparar fácilmente las diferencias de una migración. Puede utilizar el archivo de esquema para restaurar rápidamente su base de datos sin necesidad de ejecutar todas las migraciones.
Dbmate almacena un registro de cada migración aplicada en una tabla denominada schema_migrations
. Esta tabla se creará automáticamente si aún no existe.
La tabla es muy sencilla:
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR ( 255 ) PRIMARY KEY
)
Puede personalizar el nombre de esta tabla utilizando el indicador --migrations-table
o la variable de entorno DBMATE_MIGRATIONS_TABLE
.
¿Por qué otra herramienta de migración de esquemas de bases de datos? Dbmate se inspiró en muchas otras herramientas, principalmente Active Record Migrations, con el objetivo de ser trivial de configurar e independiente del lenguaje y el marco. Aquí hay una comparación entre dbmate y otras herramientas de migración populares.
compañero de base de datos | ganso | migración sql | golang-migrar | registro activo | secuelar | ruta migratoria | squatch | |
---|---|---|---|---|---|---|---|---|
Características | ||||||||
Archivos de migración SQL simples | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
Soporte para crear y eliminar bases de datos. | ✅ | ✅ | ||||||
Soporte para guardar archivos de volcado de esquema | ✅ | ✅ | ||||||
Archivos de migración con versión de marca de tiempo | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Tabla de migraciones de esquemas personalizados | ✅ | ✅ | ✅ | ✅ | ||||
Capacidad de esperar a que la base de datos esté lista | ✅ | |||||||
Cadena de conexión de base de datos cargada desde variables de entorno | ✅ | ✅ | ||||||
Cargar automáticamente el archivo .env | ✅ | |||||||
Sin archivo de configuración separado | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Idioma/marco independiente | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Conductores | ||||||||
PostgreSQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
mysql | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
SQLite | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Haga clic en Casa | ✅ | ✅ | ✅ | ✅ |
Si nota alguna inexactitud en esta tabla, proponga un cambio.
Dbmate está escrito en Go, las solicitudes de extracción son bienvenidas.
Las pruebas se ejecutan en una base de datos real utilizando Docker Compose. Para crear una imagen de Docker y ejecutar las pruebas:
$ make docker-all
Para iniciar un shell de desarrollo:
$ make docker-sh