見出し画像

難しいMigrationのハナシ


なぜMigrationか

エンジニアになりたてのころ、Migrationと聞いて「なんぞそれ」と思って検索したものの何かしっくりくる答えが得られなかった。今までなんと無くのニュアンスでやってきたが、そろそろちゃんとまとめようと思った。
つまりここの難しいって言うのは、「Migrationの専門的なお話」ではなく、当時の私にとって(多分今も)「難しくてよく分からんMigrationのメモ」的なニュアンス。

ということで聞いてみた

ググっても良い感じの答えに辿り着けなかった経験から、AIさんに聞いてみた。今はやりの(?)ChatGPTさんによるとこんな感じ

データベースのマイグレーション(Migration)は、ソフトウェア開発においてデータベースのスキーマ(データベースの構造やテーブル、カラム、インデックスなどの定義)を変更するプロセスです。新しい機能の追加、既存の構造の変更、データモデルの最適化などがその例です。

ChatGPT

つまり、わざわざDBに接続してALTER TABLE〜!!とかしなくてもいい。develop, staging, productionとかで環境を分けている場合も、それぞれにSQL叩いて変更を適用して・・・みたいな超ミスりそうな作業をしなくてもいい。Migrationファイルを一発適用してやれば、テーブル追加もカラム変更もサクゥッっとできる!

じゃあ、実際Migrationってどうやってやるか。ざっくり記載すると以下のようになる。

1. Migrationファイルを作る

2. 作ったMigrationファイルをDBに適用する

3. データの型が変わる場合は変換処理を入れる

これから実際にMigrationファイルを作っていく。


go-migrate

migrationには以下のgo-migrationを使う。今回の実装言語はGolang。

https://github.com/golang-migrate/migrate

まずはpostgresにデータベースを作る。

CREATE DATABASE temp_db;

次に、migrateコマンドを打って実際に使うMigrationファイルを生成。

// このコマンドでmigrationsディレクトリ配下にファイルが作られる
$ migrate create -ext sql -dir migrations/hoge -seq create_tmp_table

生成されたファイルの中身は空なので、ここに自分でSQLを書いていく。末尾にupとついたファイルは作成用、downと付いているのは切り戻し用のファイル。

-- 000001_create_tmp_table.up.sql
CREATE TABLE IF NOT EXISTS tmp(
    id uuid NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
    name varchar(255) NOT NULL
);
-- 000001_create_tmp_table.down.sql
drop table tmp;

いざ、Migration!!

migrateコマンドを叩いてMigrationを実行。なお、userとpassはご自分で設定したものを入れてください。

$ export POSTGRESQL_URL='postgres://user:pass@0.0.0.0:5432/temp_db?sslmode=disable'
$ migrate -database 'postgres://user:pass@0.0.0.0:5432/temp_db?sslmode=disable' -path migrations/hoge up

⚠️⚠️⚠️エラー⚠️⚠️⚠️

もしSQL文にエラーがあった場合、Migrationは失敗します。この時、上のSQLで指定したデータベースに自動でscheme_migrationsというテーブルが作成されます。ここでMigrationのステータスやバージョンが管理されています。
今はエラーでMigrationが失敗しましたが、その場合もscheme_migrationsのバージョンは上がってしまいます。この状態でMigrationを行うと、たとえ正しいSQLに書き換えていても以下のようなエラーになります。

error: Dirty database version 1. Fix and force version.

普段ならscheme_migrationsテーブルのバージョンを一つ前に戻してあげればいいのですが・・・初回だけはバージョンが0になってしまうこともあり上手くいきませんでした。なのでscheme_migrationsテーブルをdropして、再度Migrationをかけます。そうすると、以下のように成功したとメッセージが表示されます!!!

1/u create_tmp_table (49.269375ms)

 まとめ

  • Migrationって便利だね

  • でもバージョン管理でコケるとちょっと面倒だね

  • 特に初回はdirty database versionで怒られがちなので落ち着いて対処しようね

  • 困ったら自動で作られるscheme_migrationsテーブルをのぞいてみようね



参考にさせていただいたサイト

https://dev.classmethod.jp/articles/db-migrate-with-golang-migrate/


免責事項:
この記事の内容は執筆時点での情報に基づいています(2023年8月)。OpenAIのChatGPTに関する最新情報やポリシーについては、OpenAI公式ウェブサイトや公式情報源をご確認ください。本記事に記載された情報が変更された場合、それに関する最新の情報を提供するために努力いたしますが、正確性を保証するものではありません。

この記事が気に入ったらサポートをしてみませんか?