GolangでデータベースマイグレーションのDirty状態を解決する方法
Golangとgolang-migrateを使ったサーバー開発で、マイグレーションがDirty状態になった場合の対処法をまとめる。Dirty状態とは、マイグレーションが中断し、データベースが不整合な状態になったことを指す。以下に、その解決手順を備忘録的に記載する。
Dirty状態が発生する一般的なケース
Dirty状態が発生するのは、以下のようなケースが多い。
他の開発者が新しいマイグレーションを追加している場合:
他の開発者がdevelopブランチに新しいマイグレーションを追加し、それを適用して作業している。
自分のブランチに戻ると、schema_migrationsの状態とローカルのマイグレーションファイルが一致せず、Dirty状態になる。
マイグレーションの途中で中断した場合:
エラーや手動での中断により、マイグレーションが正常に完了しなかった結果、Dirty状態になる。
マイグレーションファイルの不整合:
チーム内で同期が取れておらず、必要なマイグレーションファイルが不足している場合。
テーブルschema_migrationsでDirty状態を解消
Dirty状態を解消するには、マイグレーション情報が格納されているschema_migrationsテーブルを直接修正する。
コマンド
以下のSQLでDirty状態をリセットする。
-- Dirty状態をリセット
UPDATE schema_migrations
SET dirty = FALSE
WHERE version = '<Dirtyのバージョン番号>';
実行例
例えば、マイグレーション番号が20241102のDirty状態の場合:
UPDATE schema_migrations
SET dirty = FALSE
WHERE version = '20241102';
ターミナルログ例
mysql> UPDATE schema_migrations
-> SET dirty = FALSE
-> WHERE version = '20241102';
Query OK, 1 row affected (0.01 sec)
GUIツールでの手動削除
MySQL WorkbenchなどのGUIツールを使用している場合:
・SELECT * FROM schema_migrations; でDirty状態(dirty = 1)の行を特定。
・Dirty状態の行を削除する。
DELETE FROM schema_migrations WHERE version = '<Dirtyのバージョン番号>';
状態が正常に戻ったことを確認。
forceの使用方法と注意点
golang-migrate のforceコマンドを使うと、指定したバージョンを適用済みとデータベースに記録できる。
ただし、forceは実際のマイグレーションを実行するわけではないため、未適用の状態で指定バージョンに達したとみなされる。必要に応じてupを実行してマイグレーションを完了させる。
forceとupの流れ
forceで最新のマイグレーション番号を設定:
Dirty状態を解消した後、指定したバージョンを適用済みとして設定する。
続きは、こちらで記載しています。
Discussion