go製DBスキーマ管理ツールのgooseを検証した

goose(グース)と読む forkが多くあるが、今回検証しているのはpressly/goose(ガチョウのコスプレをしたGopherが可愛い

github.com

スキーマの管理方法はオーソドックスな管理テーブルにマイグレーションファイルの適用履歴を積み上げていくタイプ

主な特徴

  • Configファイル無し
  • ドライバ内包&Go由来のシングルバイナリなので環境構築が用意
  • 本番運用に耐え得る基本的な機能はあり
  • 開発時はタイムスタンプで管理し、リリースverはインクリメンタルナンバーで管理するHybridVersioningを推している

使い勝手やGo製であるという点から競合としてsql-migrateになるか (最近利用されているのを見るsqldefは宣言的スキーマ管理というパラダイムが違うので除く)

利用方法はシンプルなので公式のREADMEなどを参照するのが一番良い

READMEになかったりする気づいた点、気になった点だけ書いていく

マイグレーションファイルを実行する以外に適用済みとすることができない

どういうことかというと、特定のマイグレーションファイルを管理対象にはしたいが色々な理由で実行はできないという場合(すでに運用されているDBのスキーマをベースラインとして登録したいなど) この場合にgooseだけでは解決できず管理テーブルに手動でマイグレーションファイルが適用済みであるというレコードをインサートする必要がある。 DjangoORMでいうfakeやflywayでいうskipExecutingMigrationsの機能といえばわかりやすい これが移行のときに非常に手間だった、ただこのシチュエーションは例外ではあるので目を瞑った

やっぱりConfigはファイルで設定できてもいいかも

自分の環境の場合殆どをMakeをタスクランナー化しCLI実行しているため、あまり問題にはならないがgooseのようにコマンドが豊富だとコマンドの数だけタスクを定義する必要があったりでやや面倒ではあった。 結果的には壊滅的な操作や細かいup/downは例外と判断し使うなら直接叩いての精神でタスク化しなかったが面倒ではある。オプションとしてConfigファイルが渡せても良いのではと思った

initのようなコマンドはなく、gooseでの初回接続時に管理テーブルが初期化される

statusコマンドなどを実行するとデフォルトではgoose_db_versionという名前で管理テーブルが作成される

version_idが0の予約されたレコードが追加されている

余談

現在gooseで検索すると上位にヒットするCyberAgentさんのブログは非常にわかりやすく有用であるが、未適用マイグレーションの扱いの挙動は現時点のverでは変わっており次の挙動となっている

  • 未適用のものがある場合マイグレーションは即座に失敗する
  • 未適用の状態はDBで管理されず、downを実行すると管理テーブルから削除される
  • --allow-migrationオプションをつけることで未適用のマイグレーションを実行することができる

管理テーブルから削除されている例 1つめのセレクトと2つめの間にdownを実行