Dbmate adalah alat migrasi basis data yang akan menjaga skema basis data Anda tetap sinkron di beberapa pengembang dan server produksi Anda.
Ini adalah alat baris perintah mandiri yang dapat digunakan dengan Go, Node.js, Python, Ruby, PHP, Rust, C++, atau bahasa atau kerangka kerja lain yang Anda gunakan untuk menulis aplikasi yang didukung database. Hal ini sangat membantu jika Anda menulis beberapa layanan dalam bahasa berbeda, dan ingin menjaga kewarasan dengan alat pengembangan yang konsisten.
Untuk perbandingan antara dbmate dan alat migrasi skema database populer lainnya, silakan lihat Alternatif.
schema.sql
untuk dengan mudah membedakan perubahan skema di gitDATABASE_URL
secara default), atau ditentukan pada baris perintah.env
AndaNPM
Instal menggunakan NPM:
npm install --save-dev dbmate
npx dbmate --help
macOS
Instal menggunakan Homebrew:
brew install dbmate
dbmate --help
Linux
Instal biner secara langsung:
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
jendela
Instal menggunakan Scoop
scoop install dbmate
dbmate -- help
Buruh pelabuhan
Gambar Docker dipublikasikan ke GitHub Container Registry ( ghcr.io/amacneil/dbmate
).
Ingatlah untuk mengatur --network=host
atau lihat komentar ini untuk tips lebih lanjut tentang menggunakan dbmate dengan jaringan buruh pelabuhan):
docker run --rm -it --network=host ghcr.io/amacneil/dbmate --help
Jika Anda ingin membuat atau menerapkan migrasi, Anda perlu menggunakan fitur pengikatan Docker untuk membuat direktori kerja lokal Anda ( pwd
) tersedia di dalam wadah 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
Opsi berikut tersedia dengan semua perintah. Anda harus menggunakan argumen baris perintah dalam urutan dbmate [global options] command [command options]
. Sebagian besar opsi juga dapat dikonfigurasi melalui variabel lingkungan (dan dimuat dari file .env
Anda, yang berguna untuk berbagi konfigurasi antar anggota tim).
--url, -u "protocol://host:port/dbname"
- tentukan url database secara langsung. (lingkungan: DATABASE_URL
)--env, -e "DATABASE_URL"
- tentukan variabel lingkungan untuk membaca URL koneksi database.--env-file ".env"
- tentukan file variabel lingkungan alternatif yang akan dimuat.--migrations-dir, -d "./db/migrations"
- tempat menyimpan file migrasi. (lingkungan: DBMATE_MIGRATIONS_DIR
)--migrations-table "schema_migrations"
- tabel database untuk mencatat migrasi. (env: DBMATE_MIGRATIONS_TABLE
)--schema-file, -s "./db/schema.sql"
- jalur untuk menyimpan file skema.sql. (lingkungan: DBMATE_SCHEMA_FILE
)--no-dump-schema
- jangan perbarui file skema.sql secara otomatis saat migrasi/kembalikan (env: DBMATE_NO_DUMP_SCHEMA
)--strict
- gagal jika migrasi diterapkan secara tidak berurutan (env: DBMATE_STRICT
)--wait
- tunggu hingga db tersedia sebelum menjalankan perintah selanjutnya (env: DBMATE_WAIT
)--wait-timeout 60s
- batas waktu untuk --wait flag (env: DBMATE_WAIT_TIMEOUT
) Dbmate menemukan database Anda menggunakan variabel lingkungan DATABASE_URL
secara default. Jika Anda menulis aplikasi dua belas faktor, Anda harus menyimpan semua string koneksi dalam variabel lingkungan.
Untuk mempermudah pengembangan, dbmate mencari file .env
di direktori saat ini, dan memperlakukan variabel apa pun yang terdaftar di sana seolah-olah variabel tersebut ditentukan dalam lingkungan saat ini (namun, variabel lingkungan yang ada lebih diutamakan).
Jika Anda belum memiliki file .env
, buat file dan tambahkan URL koneksi database Anda:
$ cat .env
DATABASE_URL= " postgres://[email protected]:5432/myapp_development?sslmode=disable "
DATABASE_URL
harus ditentukan dalam format berikut:
protocol://username:password@host:port/database_name?options
protocol
harus berupa salah satu dari mysql
, postgres
, postgresql
, sqlite
, sqlite3
, clickhouse
username
dan password
harus dikodekan URL (Anda akan mendapatkan kesalahan jika menggunakan karakter khusus)host
dapat berupa nama host atau alamat IPoptions
khusus untuk driver (lihat driver Go SQL yang mendasarinya jika Anda ingin menggunakannya) Dbmate juga dapat memuat URL koneksi dari variabel lingkungan yang berbeda. Misalnya, sebelum menjalankan rangkaian pengujian, Anda mungkin ingin menghapus dan membuat ulang database pengujian. Salah satu cara mudah untuk melakukannya adalah dengan menyimpan URL koneksi database pengujian Anda di variabel lingkungan 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 "
Anda kemudian dapat menentukan variabel lingkungan ini dalam skrip pengujian Anda (Makefile atau serupa):
$ 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
Alternatifnya, Anda dapat menentukan url langsung pada baris perintah:
$ dbmate -u " postgres://[email protected]:5432/myapp_test?sslmode=disable " up
Satu-satunya keuntungan menggunakan dbmate -e TEST_DATABASE_URL
dibandingkan dbmate -u $TEST_DATABASE_URL
adalah yang pertama memanfaatkan pemuatan file .env
otomatis dbmate.
Saat menyambung ke Postgres, Anda mungkin perlu menambahkan opsi sslmode=disable
ke string koneksi Anda, karena dbmate secara default memerlukan koneksi TLS (beberapa kerangka kerja/bahasa lain mengizinkan koneksi tidak terenkripsi secara default).
DATABASE_URL= " postgres://username:[email protected]:5432/database_name?sslmode=disable "
Parameter socket
atau host
dapat ditentukan untuk terhubung melalui soket unix (catatan: tentukan direktori saja):
DATABASE_URL= " postgres://username:password@/database_name?socket=/var/run/postgresql "
Parameter search_path
dapat digunakan untuk menentukan skema saat ini saat menerapkan migrasi, serta untuk tabel schema_migrations
dbmate. Jika skema tidak ada, maka akan dibuat secara otomatis. Jika beberapa skema yang dipisahkan koma diteruskan, skema pertama akan digunakan untuk tabel 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 "
Parameter socket
dapat ditentukan untuk terhubung melalui soket unix:
DATABASE_URL= " mysql://username:password@/database_name?socket=/var/run/mysqld/mysqld.sock "
Database SQLite disimpan di sistem file, jadi Anda tidak perlu menentukan host. Secara default, file bersifat relatif terhadap direktori saat ini. Misalnya, berikut ini akan membuat database di ./db/database.sqlite3
:
DATABASE_URL= " sqlite:db/database.sqlite3 "
Untuk menentukan jalur absolut, tambahkan garis miring ke jalur tersebut. Berikut ini akan membuat database di /tmp/database.sqlite3
:
DATABASE_URL= " sqlite:/tmp/database.sqlite3 "
DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name "
Untuk bekerja dengan cluster ClickHouse, ada 4 parameter kueri koneksi yang dapat diberikan:
on_cluster
- Indikasi untuk menggunakan pernyataan cluster dan tabel migrasi yang direplikasi. (default: false
) Jika parameter ini tidak diberikan, parameter kueri terkait klaster lainnya akan diabaikan. 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
(Opsional) - Nilai makro yang akan digunakan untuk pernyataan ON CLUSTER dan untuk jalur zookeeper mesin tabel migrasi yang direplikasi. (standar: {cluster}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&cluster_macro={my_cluster} "
replica_macro
(Opsional) - Nilai makro yang akan digunakan untuk nama replika di mesin tabel migrasi yang direplikasi. (standar: {replica}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&replica_macro={my_replica} "
zoo_path
(Opsional) - Jalur menuju migrasi tabel di ClickHouse/Zoo Keeper. (default: /clickhouse/tables/<cluster_macro>/{table}
) DATABASE_URL= " clickhouse://username:[email protected]:9000/database_name?on_cluster&zoo_path=/zk/path/tables "
Lihat opsi koneksi lain yang didukung.
Ikuti format DATABASE_URL
berikut saat menghubungkan ke BigQuery sebenarnya di GCP:
bigquery://projectid/location/dataset
projectid
(wajib) - ID Proyek
dataset
(wajib) - Nama kumpulan data dalam Proyek
location
(opsional) - Tempat Kumpulan Data dibuat
CATATAN: Ikuti dokumen ini tentang cara menyetel variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS
untuk Otentikasi yang tepat
Ikuti format berikut jika mencoba menyambung ke titik akhir khusus, misalnya BigQuery Emulator
bigquery://host:port/projectid/location/dataset?disable_auth=true
disable_auth
(opsional) - Berikan nilai true
untuk melewati Otentikasi, gunakan hanya untuk menguji dan menghubungkan ke emulator.
Dukungan Spanner saat ini terbatas pada database yang menggunakan Dialek PostgreSQL, yang harus dipilih saat pembuatan database. Untuk Spanner masa depan dengan dukungan GoogleSQL, lihat diskusi ini.
Spanner dengan antarmuka Postgres mengharuskan PGAdapter berjalan. Gunakan format berikut untuk DATABASE_URL
, dengan host dan port disetel ke tempat PGAdapter berjalan:
DATABASE_URL= " spanner-postgres://127.0.0.1:5432/database_name?sslmode=disable "
Perhatikan bahwa menentukan nama pengguna dan kata sandi tidak diperlukan, karena otentikasi ditangani oleh PGAdapter (mereka akan diabaikan oleh PGAdapter jika ditentukan).
Opsi lain dari driver postgres didukung.
Spanner juga tidak mengizinkan DDL dieksekusi di dalam transaksi eksplisit. Oleh karena itu Anda harus menentukan transaction:false
pada migrasi yang menyertakan DDL:
-- migrate:up transaction:false
CREATE TABLE ...
-- migrate:down transaction:false
DROP TABLE ...
Dump skema saat ini tidak didukung, karena pg_dump
menggunakan fungsi yang tidak disediakan oleh Spanner.
Untuk membuat migrasi baru, jalankan dbmate new create_users_table
. Anda dapat memberi nama migrasi apa pun yang Anda suka. Ini akan membuat file db/migrations/20151127184807_create_users_table.sql
di direktori saat ini:
-- migrate:up
-- migrate:down
Untuk menulis migrasi, cukup tambahkan SQL Anda ke bagian migrate:up
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
Catatan: File migrasi diberi nama dalam format
[version]_[description].sql
. Hanya versinya (didefinisikan sebagai semua karakter numerik utama dalam nama file) yang dicatat dalam database, sehingga Anda dapat dengan aman mengganti nama file migrasi tanpa mempengaruhi status aplikasinya saat ini.
Jalankan dbmate up
untuk menjalankan migrasi yang tertunda.
$ dbmate up
Creating: myapp_development
Applying: 20151127184807_create_users_table.sql
Applied: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
Catatan:
dbmate up
akan membuat database jika belum ada (dengan asumsi pengguna saat ini memiliki izin untuk membuat database). Jika Anda ingin menjalankan migrasi tanpa membuat database, jalankandbmate migrate
.
Migrasi yang tertunda selalu diterapkan dalam urutan numerik. Namun, dbmate tidak mencegah migrasi diterapkan secara tidak berurutan jika dilakukan secara independen (misalnya: jika pengembang telah bekerja di cabang untuk waktu yang lama, dan melakukan migrasi yang memiliki nomor versi lebih rendah daripada yang sudah lain- migrasi yang diterapkan, dbmate hanya akan menerapkan migrasi yang tertunda). Lihat #159 untuk penjelasan lebih detail.
Secara default, dbmate tidak tahu cara mengembalikan migrasi. Dalam pengembangan, sering kali berguna untuk mengembalikan database Anda ke keadaan sebelumnya. Untuk mencapai hal ini, terapkan bagian migrate:down
:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
email varchar ( 255 ) not null
);
-- migrate:down
drop table users;
Jalankan dbmate rollback
untuk mengembalikan migrasi terbaru:
$ dbmate rollback
Rolling back: 20151127184807_create_users_table.sql
Rolled back: 20151127184807_create_users_table.sql in 123µs
Writing: ./db/schema.sql
dbmate mendukung opsi yang diteruskan ke blok migrasi dalam bentuk pasangan key:value
. Daftar opsi yang didukung:
transaction
transaksi
transaction
berguna jika Anda tidak ingin menjalankan SQL di dalam transaksi:
-- migrate:up transaction:false
ALTER TYPE colors ADD VALUE ' orange ' AFTER ' red ' ;
transaction
akan default ke true
jika database Anda mendukungnya.
Jika Anda menggunakan lingkungan pengembangan Docker untuk proyek Anda, Anda mungkin mengalami masalah dengan database yang tidak segera siap saat menjalankan migrasi atau pengujian unit. Hal ini mungkin disebabkan oleh server database yang baru saja dimulai.
Secara umum, aplikasi Anda harus tahan terhadap tidak adanya koneksi database yang berfungsi saat startup. Namun, untuk tujuan menjalankan migrasi atau pengujian unit, hal ini tidak praktis. Perintah wait
menghindari situasi ini dengan memungkinkan Anda menjeda skrip atau aplikasi lain hingga database tersedia. Dbmate akan mencoba koneksi ke server database setiap detik, hingga maksimal 60 detik.
Jika database tersedia, wait
tidak akan menghasilkan output:
$ dbmate wait
Jika database tidak tersedia, wait
akan diblokir hingga database tersedia:
$ dbmate wait
Waiting for database....
Anda juga dapat menggunakan tanda --wait
dengan perintah lain jika terkadang Anda melihat kegagalan yang disebabkan oleh database yang belum siap:
$ dbmate --wait up
Waiting for database....
Creating: myapp_development
Anda dapat menyesuaikan batas waktu menggunakan --wait-timeout
(default 60an). Jika database masih tidak tersedia, perintah akan menampilkan kesalahan:
$ dbmate --wait-timeout=5s wait
Waiting for database.....
Error: unable to connect to database: dial tcp 127.0.0.1:5432: connect: connection refused
Harap dicatat bahwa perintah wait
tidak memverifikasi apakah database yang Anda tentukan ada, hanya server yang tersedia dan siap (sehingga akan kembali sukses jika server database tersedia, namun database Anda belum dibuat).
Saat Anda menjalankan perintah up
, migrate
, atau rollback
, dbmate akan secara otomatis membuat file ./db/schema.sql
yang berisi representasi lengkap skema database Anda. Dbmate selalu memperbarui file ini untuk Anda, jadi Anda tidak perlu mengeditnya secara manual.
Disarankan untuk memeriksa file ini ke dalam kontrol sumber, sehingga Anda dapat dengan mudah meninjau perubahan pada skema dalam permintaan penerapan atau penarikan. File ini juga dapat digunakan saat Anda ingin memuat skema database dengan cepat, tanpa menjalankan setiap migrasi secara berurutan (misalnya di test harness Anda). Namun, jika Anda tidak ingin menyimpan file ini, Anda dapat menambahkannya ke .gitignore
Anda, atau meneruskan opsi baris perintah --no-dump-schema
.
Untuk membuang file schema.sql
tanpa melakukan tindakan lain, jalankan dbmate dump
. Tidak seperti tindakan dbmate lainnya, perintah ini bergantung pada perintah pg_dump
, mysqldump
, atau sqlite3
yang tersedia di PATH Anda. Jika alat ini tidak tersedia, dbmate akan secara diam-diam melewati langkah dump skema selama tindakan up
, migrate
, atau rollback
. Anda dapat mendiagnosis masalah ini dengan menjalankan dbmate dump
dan melihat hasilnya:
$ dbmate dump
exec: " pg_dump " : executable file not found in $PATH
Pada sistem Ubuntu atau Debian, Anda dapat memperbaikinya dengan menginstal postgresql-client
, mysql-client
, atau sqlite3
. Pastikan versi paket yang Anda instal lebih besar atau sama dengan versi yang berjalan di server database Anda.
Catatan: File
schema.sql
akan berisi skema lengkap untuk database Anda, meskipun beberapa tabel atau kolom dibuat di luar migrasi dbmate.
Dbmate dirancang untuk digunakan sebagai CLI dengan bahasa atau kerangka kerja apa pun, tetapi juga dapat digunakan sebagai perpustakaan dalam aplikasi Go.
Berikut adalah contoh sederhana. Ingatlah untuk mengimpor driver yang Anda butuhkan!
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 )
}
}
Lihat dokumentasi referensi untuk opsi lebih lanjut.
Migrasi dapat disematkan ke dalam biner aplikasi Anda menggunakan fungsi penyematan Go.
Gunakan db.FS
untuk menentukan sistem file yang digunakan untuk membaca migrasi:
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 )
}
}
File migrasi sangat sederhana, dan disimpan di ./db/migrations
secara default. Anda dapat membuat file migrasi baru bernama [date]_create_users.sql
dengan menjalankan dbmate new create_users
. Berikut ini contohnya:
-- migrate:up
create table users (
id integer ,
name varchar ( 255 ),
);
-- migrate:down
drop table if exists users;
Migrasi ke atas dan ke bawah disimpan dalam file yang sama, untuk kemudahan pengeditan. Arahan ke atas dan ke bawah diperlukan, meskipun Anda memilih untuk tidak menerapkan migrasi ke bawah.
Saat Anda menerapkan migrasi, dbmate hanya menyimpan nomor versi, bukan konten, jadi Anda harus selalu mengembalikan migrasi sebelum mengubah kontennya. Karena alasan ini, Anda dapat mengganti nama file migrasi dengan aman tanpa memengaruhi status penerapannya, selama Anda tetap mempertahankan nomor versinya.
File skema ditulis ke ./db/schema.sql
secara default. Ini adalah dump lengkap skema database Anda, termasuk semua migrasi yang diterapkan, dan modifikasi lain yang telah Anda buat.
File ini harus diperiksa ke kontrol sumber, sehingga Anda dapat dengan mudah membandingkan perbedaan migrasi. Anda dapat menggunakan file skema untuk memulihkan database dengan cepat tanpa perlu menjalankan semua migrasi.
Dbmate menyimpan catatan setiap migrasi yang diterapkan dalam tabel bernama schema_migrations
. Tabel ini akan dibuat untuk Anda secara otomatis jika belum ada.
Tabelnya sangat sederhana:
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR ( 255 ) PRIMARY KEY
)
Anda dapat menyesuaikan nama tabel ini menggunakan tanda --migrations-table
atau variabel lingkungan DBMATE_MIGRATIONS_TABLE
.
Mengapa alat migrasi skema database lain? Dbmate terinspirasi oleh banyak alat lain, terutama Migrasi Rekaman Aktif, dengan tujuan agar mudah dikonfigurasi, dan tidak bergantung pada bahasa & kerangka kerja. Berikut perbandingan antara dbmate dan alat migrasi populer lainnya.
teman db | angsa | sql-migrasi | golang-migrasi | catatan aktif | sekuel | jalur terbang | sqitch | |
---|---|---|---|---|---|---|---|---|
Fitur | ||||||||
File migrasi SQL biasa | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
Dukungan untuk membuat dan menjatuhkan database | ✅ | ✅ | ||||||
Dukungan untuk menyimpan file dump skema | ✅ | ✅ | ||||||
File migrasi berversi stempel waktu | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Tabel migrasi skema kustom | ✅ | ✅ | ✅ | ✅ | ||||
Kemampuan untuk menunggu database siap | ✅ | |||||||
String koneksi database diambil dari variabel lingkungan | ✅ | ✅ | ||||||
Memuat file .env secara otomatis | ✅ | |||||||
Tidak ada file konfigurasi terpisah | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Bahasa/kerangka independen | ✅ | ✅ | ✅ | ✅ | ✅ | |||
Pengemudi | ||||||||
PostgreSQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
MySQL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
SQLite | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
KlikRumah | ✅ | ✅ | ✅ | ✅ |
Jika Anda melihat ada ketidakakuratan dalam tabel ini, harap usulkan perubahan.
Dbmate ditulis dalam Go, permintaan tarik dipersilakan.
Pengujian dijalankan terhadap database nyata menggunakan penulisan buruh pelabuhan. Untuk membuat image buruh pelabuhan dan menjalankan pengujian:
$ make docker-all
Untuk memulai shell pengembangan:
$ make docker-sh