Dbmate est un outil de migration de base de données qui maintiendra votre schéma de base de données synchronisé entre plusieurs développeurs et vos serveurs de production.
Il s'agit d'un outil de ligne de commande autonome qui peut être utilisé avec Go, Node.js, Python, Ruby, PHP, Rust, C++ ou tout autre langage ou framework que vous utilisez pour écrire des applications basées sur une base de données. Ceci est particulièrement utile si vous écrivez plusieurs services dans différentes langues et que vous souhaitez conserver un certain bon sens avec des outils de développement cohérents.
Pour une comparaison entre dbmate et d’autres outils de migration de schémas de bases de données populaires, veuillez consulter Alternatives.
schema.sql
pour comparer facilement les modifications de schéma dans gitDATABASE_URL
par défaut), ou spécifiée sur la ligne de commande.env
MNP
Installer à l'aide de NPM :
npm install --save-dev dbmate
npx dbmate --help
macOS
Installer en utilisant Homebrew :
brew install dbmate
dbmate --help
Linux
Installez le binaire directement :
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
Fenêtres
Installer à l'aide de Scoop
scoop install dbmate
dbmate -- help
Docker
Les images Docker sont publiées sur GitHub Container Registry ( ghcr.io/amacneil/dbmate
).
N'oubliez pas de définir --network=host
ou de consulter ce commentaire pour plus de conseils sur l'utilisation de dbmate avec la mise en réseau Docker) :
docker run --rm -it --network=host ghcr.io/amacneil/dbmate --help
Si vous souhaitez créer ou appliquer des migrations, vous devrez utiliser la fonctionnalité de montage de liaison de Docker pour rendre votre répertoire de travail local ( pwd
) disponible dans le conteneur 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
Les options suivantes sont disponibles avec toutes les commandes. Vous devez utiliser les arguments de ligne de commande dans l'ordre dbmate [global options] command [command options]
. La plupart des options peuvent également être configurées via des variables d'environnement (et chargées à partir de votre fichier .env
, ce qui est utile pour partager la configuration entre les membres de l'équipe).
--url, -u "protocol://host:port/dbname"
- spécifiez directement l'URL de la base de données. (environnement : DATABASE_URL
)--env, -e "DATABASE_URL"
- spécifie une variable d'environnement à partir de laquelle lire l'URL de connexion à la base de données.--env-file ".env"
- spécifie un ou plusieurs autres fichiers de variables d'environnement à charger.--migrations-dir, -d "./db/migrations"
- où conserver les fichiers de migration. (environnement : DBMATE_MIGRATIONS_DIR
)--migrations-table "schema_migrations"
- table de base de données dans laquelle enregistrer les migrations. (env : DBMATE_MIGRATIONS_TABLE
)--schema-file, -s "./db/schema.sql"
- un chemin pour conserver le fichier schema.sql. (environnement : DBMATE_SCHEMA_FILE
)--no-dump-schema
- ne met pas à jour automatiquement le fichier schema.sql lors de la migration/rollback (env : DBMATE_NO_DUMP_SCHEMA
)--strict
- échoue si les migrations sont appliquées dans le désordre (env : DBMATE_STRICT
)--wait
- attendez que la base de données soit disponible avant d'exécuter la commande suivante (env : DBMATE_WAIT
)--wait-timeout 60s
- délai d'attente pour l'indicateur --wait (env : DBMATE_WAIT_TIMEOUT
) Dbmate localise votre base de données à l'aide de la variable d'environnement DATABASE_URL
par défaut. Si vous écrivez une application à douze facteurs, vous devez stocker toutes les chaînes de connexion dans des variables d'environnement.
Pour faciliter le développement, dbmate recherche un fichier .env
dans le répertoire courant et traite toutes les variables qui y sont répertoriées comme si elles étaient spécifiées dans l'environnement actuel (les variables d'environnement existantes ont cependant la préférence).
Si vous n'avez pas déjà de fichier .env
, créez-en un et ajoutez l'URL de connexion à votre base de données :
$ cat .env
DATABASE_URL= " postgres://[email protected]:5432/myapp_development?sslmode=disable "
DATABASE_URL
doit être spécifié au format suivant :
protocol://username:password@host:port/database_name?options
protocol
doit être l'un des suivants mysql
, postgres
, postgresql
, sqlite
, sqlite3
, clickhouse
username
et password
doivent être codés en URL (vous obtiendrez une erreur si vous utilisez des caractères spéciaux)host
peut être soit un nom d'hôte, soit une adresse IPoptions
sont spécifiques au pilote (reportez-vous aux pilotes Go SQL sous-jacents si vous souhaitez les utiliser) Dbmate peut également charger l'URL de connexion à partir d'une variable d'environnement différente. Par exemple, avant d'exécuter votre suite de tests, vous souhaiterez peut-être supprimer et recréer la base de données de test. Un moyen simple de procéder consiste à stocker l'URL de connexion à votre base de données de test dans la variable d'environnement 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 "
Vous pouvez ensuite spécifier cette variable d'environnement dans votre script de test (Makefile ou similaire) :
$ 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
Alternativement, vous pouvez spécifier l'url directement sur la ligne de commande :
$ dbmate -u " postgres://[email protected]:5432/myapp_test?sslmode=disable " up
Le seul avantage de l'utilisation dbmate -e TEST_DATABASE_URL
par rapport à dbmate -u $TEST_DATABASE_URL
est que le premier profite du chargement automatique du fichier .env
de dbmate.
Lors de la connexion à Postgres, vous devrez peut-être ajouter l'option sslmode=disable
à votre chaîne de connexion, car dbmate nécessite par défaut une connexion TLS (certains autres frameworks/langages autorisent les connexions non chiffrées par défaut).
DATABASE_URL= " postgres://username:[email protected]:5432/database_name?sslmode=disable "
Un paramètre socket
ou host
peut être spécifié pour se connecter via un socket unix (remarque : spécifiez uniquement le répertoire) :
DATABASE_URL= " postgres://username:password@/database_name?socket=/var/run/postgresql "
Un paramètre search_path
peut être utilisé pour spécifier le schéma actuel lors de l'application des migrations, ainsi que pour la table schema_migrations
de dbmate. Si le schéma n'existe pas, il sera créé automatiquement. Si plusieurs schémas séparés par des virgules sont transmis, le premier sera utilisé pour la table 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 "
Un paramètre socket
peut être spécifié pour se connecter via un socket Unix :
DATABASE_URL= " mysql://username:password@/database_name?socket=/var/run/mysqld/mysqld.sock "
Les bases de données SQLite sont stockées sur le système de fichiers, vous n'avez donc pas besoin de spécifier un hôte. Par défaut, les fichiers sont relatifs au répertoire courant. Par exemple, ce qui suit créera une base de données sur ./db/database.sqlite3
:
DATABASE_URL= " sqlite:db/database.sqlite3 "
Pour spécifier un chemin absolu, ajoutez une barre oblique au chemin. Ce qui suit créera une base de données dans /tmp/database.sqlite3
:
DATABASE_URL= " sqlite:/tmp/database.sqlite3 "
DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name "
Pour travailler avec le cluster ClickHouse, 4 paramètres de requête de connexion peuvent être fournis :
on_cluster
- Indication d'utiliser les instructions de cluster et la table de migration répliquée. (par défaut : false
) Si ce paramètre n'est pas fourni, les autres paramètres de requête liés au cluster sont ignorés. 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
(Facultatif) - Valeur de macro à utiliser pour les instructions ON CLUSTER et pour le chemin du gardien de zoo du moteur de table de migration répliqué. (par défaut : {cluster}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&cluster_macro={my_cluster} "
replica_macro
(Facultatif) : valeur de macro à utiliser pour le nom de la réplique dans le moteur de table de migration répliquée. (par défaut : {replica}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&replica_macro={my_replica} "
zoo_path
(Facultatif) - Le chemin d'accès à la migration de la table dans ClickHouse/Zoo Keeper. (par défaut : /clickhouse/tables/<cluster_macro>/{table}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&zoo_path=/zk/path/tables "
Consultez les autres options de connexion prises en charge.
Suivez le format suivant pour DATABASE_URL
lors de la connexion à BigQuery dans GCP :
bigquery://projectid/location/dataset
projectid
(obligatoire) - ID du projet
dataset
(obligatoire) - Nom de l'ensemble de données dans le projet
location
(facultatif) - Où l'ensemble de données est créé
REMARQUE : suivez ce document pour savoir comment définir la variable d'environnement GOOGLE_APPLICATION_CREDENTIALS
pour une authentification appropriée.
Suivez le format suivant si vous essayez de vous connecter à un point de terminaison personnalisé, par exemple BigQuery Emulator.
bigquery://host:port/projectid/location/dataset?disable_auth=true
disable_auth
(facultatif) - Passez true
pour ignorer l'authentification, à utiliser uniquement pour tester et se connecter à l'émulateur.
La prise en charge de Spanner est actuellement limitée aux bases de données utilisant le dialecte PostgreSQL, qui doit être choisi lors de la création de la base de données. Pour le futur support de Spanner avec GoogleSQL, consultez cette discussion.
Spanner avec l'interface Postgres nécessite que le PGAdapter soit en cours d'exécution. Utilisez le format suivant pour DATABASE_URL
, avec l'hôte et le port définis sur l'endroit où le PGAdapter est exécuté :
DATABASE_URL= " spanner-postgres://127.0.0.1:5432/database_name?sslmode=disable "
Notez qu'il n'est pas nécessaire de spécifier un nom d'utilisateur et un mot de passe, car l'authentification est gérée par le PGAdapter (ils seront ignorés par le PGAdapter s'ils sont spécifiés).
D'autres options du pilote postgres sont prises en charge.
Spanner ne permet pas non plus d'exécuter DDL dans des transactions explicites. Vous devez donc spécifier transaction:false
sur les migrations qui incluent DDL :
-- migrate:up transaction:false
CREATE TABLE ...
-- migrate:down transaction:false
DROP TABLE ...
Les dumps de schéma ne sont actuellement pas pris en charge, car pg_dump
utilise des fonctions qui ne sont pas fournies par Spanner.
Pour créer une nouvelle migration, exécutez dbmate new create_users_table
. Vous pouvez nommer la migration comme vous le souhaitez. Cela créera un fichier db/migrations/20151127184807_create_users_table.sql
dans le répertoire courant :
-- migrate:up
-- migrate:down
Pour écrire une migration, ajoutez simplement votre code SQL à la section migrate:up
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
Remarque : Les fichiers de migration sont nommés au format
[version]_[description].sql
. Seule la version (définie par tous les caractères numériques de début du nom de fichier) est enregistrée dans la base de données, vous pouvez donc renommer un fichier de migration en toute sécurité sans avoir aucun effet sur son état actuel d'application.
Exécutez dbmate up
pour exécuter toutes les migrations en attente.
$ dbmate up
Creating: myapp_development
Applying: 20151127184807_create_users_table.sql
Applied: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
Remarque :
dbmate up
créera la base de données si elle n'existe pas déjà (en supposant que l'utilisateur actuel ait l'autorisation de créer des bases de données). Si vous souhaitez exécuter des migrations sans créer la base de données, exécutezdbmate migrate
.
Les migrations en attente sont toujours appliquées par ordre numérique. Cependant, dbmate n'empêche pas les migrations d'être appliquées dans le désordre si elles sont validées indépendamment (par exemple : si un développeur travaille sur une branche depuis longtemps et valide une migration qui a un numéro de version inférieur à celui d'autres déjà). migrations appliquées, dbmate appliquera simplement la migration en attente). Voir #159 pour une explication plus détaillée.
Par défaut, dbmate ne sait pas comment annuler une migration. En développement, il est souvent utile de pouvoir restaurer votre base de données à un état antérieur. Pour ce faire, implémentez la section migrate:down
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
drop table users;
Exécutez dbmate rollback
pour restaurer la migration la plus récente :
$ dbmate rollback
Rolling back: 20151127184807_create_users_table.sql
Rolled back: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
dbmate prend en charge les options transmises à un bloc de migration sous la forme de paires key:value
. Liste des options prises en charge :
transaction
transaction
transaction
est utile si vous ne souhaitez pas exécuter SQL dans une transaction :
-- migrate:up transaction:false
ALTER TYPE colors ADD VALUE ' orange ' AFTER ' red ' ;
transaction
sera par défaut true
si votre base de données la prend en charge.
Si vous utilisez un environnement de développement Docker pour votre projet, vous pouvez rencontrer des problèmes avec la base de données qui n'est pas immédiatement prête lors de l'exécution de migrations ou de tests unitaires. Cela peut être dû au fait que le serveur de base de données vient tout juste de démarrer.
En général, votre application doit être résiliente à ne pas avoir de connexion à la base de données fonctionnelle au démarrage. Cependant, dans le but d’exécuter des migrations ou des tests unitaires, cela n’est pas pratique. La commande wait
évite cette situation en vous permettant de suspendre un script ou une autre application jusqu'à ce que la base de données soit disponible. Dbmate tentera de se connecter au serveur de base de données toutes les secondes, jusqu'à un maximum de 60 secondes.
Si la base de données est disponible, wait
ne renverra aucune sortie :
$ dbmate wait
Si la base de données est indisponible, wait
sera bloqué jusqu'à ce que la base de données soit disponible :
$ dbmate wait
Waiting for database....
Vous pouvez également utiliser l'option --wait
avec d'autres commandes si vous constatez parfois des échecs causés par le fait que la base de données n'est pas encore prête :
$ dbmate --wait up
Waiting for database....
Creating: myapp_development
Vous pouvez personnaliser le délai d'attente en utilisant --wait-timeout
(60 s par défaut). Si la base de données n'est toujours pas disponible, la commande renverra une erreur :
$ dbmate --wait-timeout=5s wait
Waiting for database.....
Error: unable to connect to database: dial tcp 127.0.0.1:5432: connect: connection refused
Veuillez noter que la commande wait
ne vérifie pas si la base de données spécifiée existe, mais uniquement que le serveur est disponible et prêt (elle renverra donc un succès si le serveur de base de données est disponible, mais que votre base de données n'a pas encore été créée).
Lorsque vous exécutez les commandes up
, migrate
ou rollback
, dbmate crée automatiquement un fichier ./db/schema.sql
contenant une représentation complète de votre schéma de base de données. Dbmate maintient ce fichier à jour pour vous, vous ne devez donc pas le modifier manuellement.
Il est recommandé d'archiver ce fichier dans le contrôle de source, afin que vous puissiez facilement examiner les modifications apportées au schéma dans les validations ou les demandes d'extraction. Il est également possible d'utiliser ce fichier lorsque vous souhaitez charger rapidement un schéma de base de données, sans exécuter chaque migration de manière séquentielle (par exemple dans votre harnais de test). Cependant, si vous ne souhaitez pas enregistrer ce fichier, vous pouvez l'ajouter à votre .gitignore
ou passer l'option de ligne de commande --no-dump-schema
.
Pour vider le fichier schema.sql
sans effectuer aucune autre action, exécutez dbmate dump
. Contrairement aux autres actions dbmate, cette commande repose sur la disponibilité des commandes pg_dump
, mysqldump
ou sqlite3
dans votre PATH. Si ces outils ne sont pas disponibles, dbmate ignorera silencieusement l'étape de vidage du schéma lors des actions up
, migrate
ou rollback
. Vous pouvez diagnostiquer le problème en exécutant dbmate dump
et en consultant le résultat :
$ dbmate dump
exec: " pg_dump " : executable file not found in $PATH
Sur les systèmes Ubuntu ou Debian, vous pouvez résoudre ce problème en installant respectivement postgresql-client
, mysql-client
ou sqlite3
. Assurez-vous que la version du package que vous installez est supérieure ou égale à la version exécutée sur votre serveur de base de données.
Remarque : Le fichier
schema.sql
contiendra un schéma complet pour votre base de données, même si certaines tables ou colonnes ont été créées en dehors des migrations dbmate.
Dbmate est conçu pour être utilisé comme CLI avec n'importe quel langage ou framework, mais il peut également être utilisé comme bibliothèque dans une application Go.
Voici un exemple simple. Pensez à importer le pilote dont vous avez besoin !
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 )
}
}
Consultez la documentation de référence pour plus d’options.
Les migrations peuvent être intégrées au binaire de votre application à l'aide de la fonctionnalité d'intégration de Go.
Utilisez db.FS
pour spécifier le système de fichiers utilisé pour lire les migrations :
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 )
}
}
Les fichiers de migration sont très simples et sont stockés par défaut dans ./db/migrations
. Vous pouvez créer un nouveau fichier de migration nommé [date]_create_users.sql
en exécutant dbmate new create_users
. Voici un exemple :
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
);
-- migrate:down
drop table if exists users;
Les migrations ascendantes et descendantes sont stockées dans le même fichier, pour faciliter l'édition. Les directives up et down sont requises, même si vous choisissez de ne pas implémenter la migration vers le bas.
Lorsque vous appliquez une migration, dbmate stocke uniquement le numéro de version, pas le contenu. Vous devez donc toujours annuler une migration avant de modifier son contenu. Pour cette raison, vous pouvez renommer un fichier de migration en toute sécurité sans affecter son statut d'application, à condition de conserver le numéro de version intact.
Le fichier de schéma est écrit par défaut dans ./db/schema.sql
. Il s'agit d'un vidage complet de votre schéma de base de données, y compris toutes les migrations appliquées et toutes les autres modifications que vous avez apportées.
Ce fichier doit être archivé dans le contrôle de code source, afin que vous puissiez facilement comparer les différences d'une migration. Vous pouvez utiliser le fichier schéma pour restaurer rapidement votre base de données sans avoir à exécuter toutes les migrations.
Dbmate stocke un enregistrement de chaque migration appliquée dans la table nommée schema_migrations
. Ce tableau sera créé automatiquement pour vous s'il n'existe pas déjà.
Le tableau est très simple :
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR ( 255 ) PRIMARY KEY
)
Vous pouvez personnaliser le nom de cette table à l'aide de l'indicateur --migrations-table
ou de la variable d'environnement DBMATE_MIGRATIONS_TABLE
.
Pourquoi un autre outil de migration de schéma de base de données ? Dbmate s'est inspiré de nombreux autres outils, principalement Active Record Migrations, dans le but d'être simple à configurer et indépendant du langage et du framework. Voici une comparaison entre dbmate et d'autres outils de migration populaires.
dbmate | oie | migration SQL | golang-migrer | enregistrement actif | séquelle | voie de migration | piquer | |
---|---|---|---|---|---|---|---|---|
Caractéristiques | ||||||||
Fichiers de migration SQL simples | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
Prise en charge de la création et de la suppression de bases de données | ✅ | ✅ | ||||||
Prise en charge de l'enregistrement des fichiers de vidage de schéma | ✅ | ✅ | ||||||
Fichiers de migration avec version d'horodatage | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Tableau des migrations de schémas personnalisés | ✅ | ✅ | ✅ | ✅ | ||||
Possibilité d'attendre que la base de données soit prête | ✅ | |||||||
Chaîne de connexion à la base de données chargée à partir de variables d'environnement | ✅ | ✅ | ||||||
Charger automatiquement le fichier .env | ✅ | |||||||
Pas de fichier de configuration séparé | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Indépendant du langage/du framework | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Pilotes | ||||||||
PostgreSQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
MySQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
SQLite | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Cliquez sur Maison | ✅ | ✅ | ✅ | ✅ |
Si vous remarquez des inexactitudes dans ce tableau, veuillez proposer une modification.
Dbmate est écrit en Go, les pull request sont les bienvenues.
Les tests sont exécutés sur une base de données réelle à l'aide de Docker Compose. Pour créer une image Docker et exécuter les tests :
$ make docker-all
Pour démarrer un shell de développement :
$ make docker-sh