Go言語でDBのスキーマをうまく管理してくれるツール無いの?というところで試したツールの一つ。
skeema/skeema: Schema management CLI for MySQL
ザックリ言うと、RailsでいうActiveRecord::Schemaみたいなスキーマダンプを作ってくれるやつ。
環境
- macOS Catalina
- go version 1.13.4
記事執筆時点で対応しているデータベース
MySQL系のプロダクトの模様。
- MySQL 5.5, 5.6, 5.7, 8.0
- Percona Server 5.5, 5.6, 5.7, 8.0
- MariaDB 10.1, 10.2, 10.3, 10.4
準備
go get -u github.com/skeema/skeema
使い方
現在のスキーマをダンプ
下記のコマンドを適宜編集して実行する。
skeema init -h my.db.hostname -u root -p -d schemas --schema dbname
するとschemas
ディレクトリ以下にテーブルごとにDDLがファイルが出力される。
-d
で指定したディレクトリにダンプされる。
--schema
オプション無しの場合は、ユーザーが作ったすべてのデータベース毎のディレクトリが作られ、その中にそれぞれのデータベースにあるテーブル定義が出力される。
--schema
ありの場合は、指定ディレクトリの直下にファイルが出力される。
skeema init --help
で詳細なオプションを確認できる。
この時の接続情報は.skeema
ファイルに記録されている。
スキーマを変更して適用
例えば以下のように変更してみる。
CREATE TABLE `applications` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`ios_bundle_name` varchar(255) DEFAULT NULL,
`android_bundle_name` varchar(255) DEFAULT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`deleted_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
↓
CREATE TABLE `applications` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(256) NOT NULL,
`ios_bundle_name` varchar(255) DEFAULT '',
`android_bundle_name` varchar(255) DEFAULT NULL,
`created_at` datetime,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
これを適用してみる。
まず差分をチェックする。
skeema diff
で実際にどのようなSQL文が発行されるかを確認できる。
今回は列の削除が含まれるので、--allow-unsafe
オプションが必要。
$ skeema diff -p --allow-unsafe
:
-- instance: localhost:/tmp/mysql.sock
USE `testdb`;
ALTER TABLE `applications` DROP COLUMN `deleted_at`, MODIFY COLUMN `name` varchar(256) NOT NULL, MODIFY COLUMN `ios_bundle_name` varchar(255) DEFAULT '', MODIFY COLUMN `created_at` datetime DEFAULT NULL, ADD UNIQUE KEY `name` (`name`);
次に実際に適用してみる。
$ skeema push -p --allow-unsafe
:
-- instance: localhost:/tmp/mysql.sock
USE `testdb`;
ALTER TABLE `applications` DROP COLUMN `deleted_at`, MODIFY COLUMN `name` varchar(256) NOT NULL, MODIFY COLUMN `ios_bundle_name` varchar(255) DEFAULT '', MODIFY COLUMN `created_at` datetime DEFAULT NULL, ADD UNIQUE KEY `name` (`name`);
2020-03-15 14:44:46 [INFO] localhost:/tmp/mysql.sock testdb: push complete
Sequel Proなどで軽く確認すると、適用されている事が分かる。
ここでは記載していないが、テーブルの追加や削除にも対応している。
削除時には--allow-unsafe
が必要。
スキーマの差分を反映する
直接本番で作業した、開発環境でテーブルをGUIで変更したなどの理由で差分をDDLに反映させたい場合などがあるだろう。
そういう場合にはskeema pull
を利用できる。
$ skeema pull -p
Enter password:
2020-03-15 14:59:13 [INFO] Updating /path/to/schemas to reflect localhost:/tmp/mysql.sock testdb
2020-03-15 14:59:13 [INFO] Wrote /path/to/schemas/applications.sql (425 bytes)
フォーマット
skeema format -p
でSQL文の整形ができる。
lint
skeema lint -p
でlintできる。こんな感じ。
2020-03-15 14:40:52 [INFO] Linting /path/to/schemas
2020-03-15 14:40:53 [WARN] /path/to/schemas/applications.sql:2: Column id of table applications is an auto_increment column
using data type int, which is not configured to be permitted. The following data types are listed in option
allow-auto-inc: int unsigned, bigint unsigned.
In general, auto_increment columns should be unsigned, since behavior of auto_increment is undefined with negative
numbers.
2020-03-15 14:40:53 [WARN] Found 1 warnings
GitHubにインストールして使えるCIサービスもある。現在ベータ版で無料。
環境を分ける
最初に生成されるのはproduction
の設定だが、develop
やstaging
など環境を追加する事も可能。
残念な事に、データベース名(scheme)は共通となっており、本番と合わせる必要がある。
$ skeema add-environment development -h localhost -u root -p
2020-03-15 15:01:46 [INFO] Added environment [development] to /path/to/schemas/.skeema
環境を指定する際は一番最後に付ける。
skeema pull -p development
など。
お察しの通り、何も指定しない場合はproduction
になる。
どちらかと言うと本番の時に指定させて欲しいところだが…