Skip to content

Instantly share code, notes, and snippets.

@SnowCait
Last active June 19, 2018 01:59
Show Gist options
  • Save SnowCait/7d5412867d02fa980c30780baca2738e to your computer and use it in GitHub Desktop.
Save SnowCait/7d5412867d02fa980c30780baca2738e to your computer and use it in GitHub Desktop.
Migration

マイグレーション

要件

  • 実行言語に依存しない定義(JSON, SQL)
  • up, down, バージョン指定
  • シャーディング対応(同一DB名、同一テーブル名)
  • 同時に追加しようとした場合にコンフリクトさせる

仕様

up, down, バージョン指定

  • 未定義の場合はエラーにする
  • 1つのバージョンはトランザクションで実行する、失敗した場合はロールバック

同時に追加しようとした場合にコンフリクトさせる

generateコマンドでファイルを生成する際にファイル名にタイムスタンプを付加するのが一般的だが、 それだと複数ブランチで生成した場合に順番が保証されない。 コンフリクトさせるなどして順番を保証する。 バージョンの管理と定義を分けることにより実現。

規約

  • 想定と異なるテーブルが存在していた場合に気付きにくいのでIF [NOT] EXISTSはなるべく書かない

メリット

  • フレームワーク毎に異なる構文ではなくSQLで直接書ける no more huge document.

デメリット

  • RDBMSの違いによるSQLの差異を吸収できない  → 途中で変更することはほとんどないと思われるので影響は少ない

実装

Command

migrator help
migrator status # バージョン一覧+現在のバージョン
migrator version # 現在のバージョン
migrator migrate
migrator rollback --step=1
migration-helper generate down [path]

config.json

{
  "db1": {
    "driver": "mysql"
    "host": localhost,
    "db": "db1",
    "user": "root",
    "pass": "root"
  },
  "db2": {
    "dns": "mysql:host=localhost;dbname=db2",
    "user": "root",
    "pass": "root"
  }
}

versions.json

[
  {
    "db": "db1",
    "up": "001/table1.up.sql",
    "down": "001/table1.down.sql"
  },
  {
    "db": ["db1", "db2"],
    "up": "001/*.up.sql",
    "down": "001/*.down.sql"
  }
]

要望

  • CREATE文だけ定義してALTERを差分から自動生成、差分はGitなどから取得できるとなお良い
  • パーティションの管理
  • データベースの作成、ユーザーの作成などテーブルのマイグレーション以外も含める?

参考

class Migrator
{
public void Initialize()
{
}
public void Up()
{
}
public void Down()
{
}
}

Q&A

  • なぜDSLを使わないか
    • 確かにDSLを使えば1つのコードで様々なRDBMSに対応できます。しかしDSLにしてしまうと学習コストが発生します。途中でRDBMSを変更することは稀だと思われるので学習コストを下げる選択をしました。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment