はじめに
チーム開発時、マージのタイミングなどでalmbicのバージョンがおかしくなってしまうことがあります。
その対処法を備忘録として残しておきます。
例として、migrationスクリプトの実行順は、以下のようになっているとします。
実際の環境では、alembic history
を実行するとスクリプトの実行順が確認できます。
8wp6ak79my83 # 最初のスクリプト
9j9u6f5ipni7
m9xydtn3xynj
ipmk4tzf57xy
5j4gmsz2te8w
m54f6fc82n62
hku9seazdc7k # head
現在のバージョンを調べる
alembic current
を実行すると、現在のalembicのバージョンがわかります。
以下の例だと、"m9xydtn3xynj" まで実行されていることがわかります。なので、この状態でalembic upgrade head
とすると、"m9xydtn3xynj"の次に実行されるスクリプトから順に実行されていくことになります。
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
m9xydtn3xynj (branchpoint)
8wp6ak79my83 # 最初のスクリプト
9j9u6f5ipni7
m9xydtn3xynj # alembicはここまで実行したと思っている
ipmk4tzf57xy
5j4gmsz2te8w
m54f6fc82n62
hku9seazdc7k # head
次に実行すべきスクリプトを特定する
次どのスクリプトを実行すればOKなのかを調べます。
実際のDBと見比べてみて、差分が生じる操作をするスクリプトからスタートすればOKです。
alembic upgrade head
を実行して失敗したときのエラーメッセージから大体検討がつくと思います。たとえば、以下のエラーメッセージであれば、「実際のDBには存在するFooテーブルは、alembic的にはまだ作ってないことになっているんだな」とわかります。なので、Fooテーブルを作っているスクリプトの次のスクリプトを実行すれば良さそう、みたいな感じです。
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.DuplicateTable) relation "Foo" already exists
alembic/versions
ディレクトリを見て、"5j4gmsz2te8w"がFooテーブルを作るスクリプトだと分かったとします。するとその次のスクリプト"m54f6fc82n62"から実行すれば良さそう、と検討がつきます。
8wp6ak79my83 # 最初のスクリプト
9j9u6f5ipni7
m9xydtn3xynj # alembicはここまで実行したと思っている
ipmk4tzf57xy
5j4gmsz2te8w # Fooテーブルを作るスクリプト
m54f6fc82n62 # ここから実行すればOKなはず
hku9seazdc7k # head
Alembicのバージョンを変更する
Alembicは、実行したmigrationの最新バージョンがどれか、という情報をalembic_version
テーブルに保持しています。テーブルを見てみると、alembic current
で出力されるバージョンと同じ値が入っているかと思います。
SELECT * FROM alembic_version;
version_num
---------------------
m9xydtn3xynj
これを、Fooテーブルを作るスクリプト"5j4gmsz2te8w" に変更してやると、Alembicは「"5j4gmsz2te8w"まで実行した」と認識してくれるようになります。
この状態でalembic upgrade head
とすると、"m54f6fc82n62"から"head"までのスクリプトが実行されます。
alembic upgrade head を実行
alembic upgrade head
を実行して、結果をみてみます。
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade 5j4gmsz2te8w -> m54f6fc82n62, <message>
INFO [alembic.runtime.migration] Running upgrade m54f6fc82n62 -> hku9seazdc7k, <message>
無事headまで実行されたようです。再度DBの状態とmigrationスクリプトを見比べてみて、問題なければOKです。
alembic_version
にも、headのバージョンが格納されているはずです。
SELECT * FROM alembic_version;
version_num
---------------------
hku9seazdc7k
参考