LoginSignup
24
19

More than 3 years have passed since last update.

Python Migration Toolを徹底比較してみた

Last updated at Posted at 2021-02-21

概要

Djangoのようなフレームワークを使う際にはMigration Toolが内蔵されていますので特にどのツールを使おうか悩むことはないかと思いますが、FastAPIやFlaskなどの軽量フレームワークを使う際、Migration Toolを選定する必要があるかと思います。

そんな方のために現時点において主要な三つのPythonのMigration Toolをまとめてみました。

(2021/2/20現在)

Github Github Stars Github最終更新日 対応DB DSL/RawSQL ドキュメント
alembic https://github.com/sqlalchemy/alembic 834 11 hours ago MySQL, SQLServer,Postgresql, SQLite Python/Raw SQL https://alembic.sqlalchemy.org/en/latest/
simple-db-migrate https://github.com/guilhermechapiewski/simple-db-migrate 186 5 months ago MySQL Raw SQL Githubのみ
yoyo-migration https://github.com/marcosschroh/yoyo-database-migrations 9 13 months ago PostgreSQL, MySQL, SQLite Python / Raw SQL https://ollycope.com/software/yoyo/latest/

ざっと比較表を見るとalembicが圧倒的ですね。
実際Flaskによく使われるFlask-migrationもalembicをwrapしたものであり、Flaskに次ぐ軽量フレームワークのFastAPIも公式はalembicを推奨しています(https://fastapi.tiangolo.com/ja/tutorial/sql-databases/#alembic-note)

現時点においてはalembicとsimple-db-migrateが二大勢力といった感じでしょうか。
ですのでこの記事では主要な二つのPython Migration Toolであるalembicとsimple-db-migrateを比較していこうと思います!

それではまずalembicから使い方とメリデメを見ていきましょう!

alembic

Alembic is a database migrations tool written by the author of SQLAlchemy.

とGithubのREADMEに書いてあるとおり、sqlalchemyの作者が作っただけあってsqlalchemyとの互換性は抜群です。
autogenerateという機能を備え、sqlalchemyで定義したschemaから自動でMigration scriptを作成できます。

基本的な使い方

install

pip install alembic

(適宜使っているpackage管理ツールに置き換えてください)

alembic環境構築

alembicはテンプレートの中から目的にあった設定ファイルをサクッと作ることができます。

$ alembic list_templates
Available templates:

generic - Generic single-database configuration.
multidb - Rudimentary multi-database configuration.
pylons - Configuration that reads from a Pylons project environment.

Templates are used via the 'init' command, e.g.:

  alembic init --template pylons ./scripts

マイグレーションファイルの作成

基本的な作成方法は以下のコマンドを打って作成されるファイルにPythonまたはRawSQLでスクリプトを追加していくことです。

$ alembic revision -m "Add a column"
Generating /path/to/yourapp/alembic/versions/ae1027a6acf_add_a_column.py...
done
ae1027a6acf_add_a_column.py
"""Add a column

Revision ID: ae1027a6acf
Revises: 1975ea83b712
Create Date: 2011-11-08 12:37:36.714947

"""

# revision identifiers, used by Alembic.
revision = 'ae1027a6acf'
down_revision = '1975ea83b712'

from alembic import op
import sqlalchemy as sa

def upgrade():
    # Migration適応内容記入
    # 例 op.add_column('account', sa.Column('last_transaction_date', sa.DateTime))

def downgrade():
    # rollback時適応内容記入
    # 例 op.drop_column('account', 'last_transaction_date')

しかしこのような使い方をしているのではalembicの恩恵を十分に受けられません。

alembic最大の強みはsqlalchemyで定義したモデルschemaを元に自動でMigration Scriptを生成してくれることです!

Auto generate機能

Auto generate機能を使うにはデフォルトで作成されたenv.pyファイルの中身を以下のように変更する必要があります。

env.py(変更前)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = None
env.py(変更後)

from myapp.mymodel import Base (sqlalchemyで定義したモデルからdeclarative_baseをimport)
target_metadata = Base.metadata

変更後--autogenerateをつけるだけでmodel schemaを元に自動でMigration Scriptが作成されます!

$ alembic revision --autogenerate -m "Added account table"
INFO [alembic.context] Detected added table 'account'
Generating /path/to/foo/alembic/versions/27c6a30d7c24.py...done
27c6a30d7c24.py
"""empty message

Revision ID: 27c6a30d7c24
Revises: None
Create Date: 2011-11-08 11:40:27.089406

"""

# revision identifiers, used by Alembic.
revision = '27c6a30d7c24'
down_revision = None

from alembic import op
import sqlalchemy as sa

def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
    'account',
    sa.Column('id', sa.Integer()),
    sa.Column('name', sa.String(length=50), nullable=False),
    sa.Column('description', sa.VARCHAR(200)),
    sa.Column('last_transaction_date', sa.DateTime()),
    sa.PrimaryKeyConstraint('id')
    )
    ### end Alembic commands ###

def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_table("account")
    ### end Alembic commands ###

Auto generate...強力ですね!
自分も最初使った時は思わず「alembic様、天才!」と声をあげそうになりました。

こうして作られたMigration scriptを実行していきましょう。

マイグレーションの実行

alembic upgrade head

このコマンド一発でDBにMigration Scriptが実行されます。
DBを見てみるとalembic_versionと言うテーブルが作られており、version_numというカラムの中に最後に当てられたMigration fileのrevisionが保存されます。

この値を元にalembicはバージョン管理をし、rollbackを可能にしています。

rollbackをするには

alembic downgrade -1

で一つ前のmigrationを取り消すことができ、複数前のrevisionまでrollbackするには、

alembic history

でrevision情報を表示し、戻りたいrevisionを指定し

alembic downgrade {revision}

で遡ることができます。

以上が基本的な使い方ですが他の機能も紹介しておきたいと思います。

tips

メリット

メリットとしては以下の点があげられます。

  • sqlalchemyで定義したschemaからmigration scriptを自動生成するauto generate機能

  • 複数DB接続 / 環境によってDBを切り替えられる

  • Python、Raw SQLの両方でMigration scriptをかける

  • Communityが大きい/SQLAlchemyの作者がContributeしていることから今後も機能拡張される

デメリット

一番の欠点はautogenerateと言う素晴らしい機能を備えていますが、必ずしも万能ではないことです。

Auto generateで検知できない変更として以下の点があります。

  • テーブル名の変更(drop/addになりデータが初期化されます)
  • カラム名の変更(drop/addになりデータが初期化されます)
  • 名前の付いていないユニーク制約 (変更を検知するにはユニーク制約に名前をつけることは必須(e.g. UniqueConstraint('col1', 'col2', name="my_name"))
  • EnumなどのSQLAlchemy特有のカラムの変更
  • Columnの順番の指定

What does Autogenerate Detect (and what does it not detect?)

なので運用方法としては基本的にはauto generate、うまく生成されない場合は自分でマニュアルで記入する対応が必要になりそうです。

simple-db-migrate

simple-db-migrate is damn simple. The best way to understand how it works is by installing and using it.

続いてsimple-db-migrateを試してみましょう。
simple-db-migrateはその名の通りめちゃめちゃシンプルなMigration Toolです。

基本的な使い方

install

$ pip install simple-db-migrate

設定ファイルの作成

$ touch simple-db-migrate.conf
simple-db-migrate.conf
DATABASE_HOST = "localhost"
DATABASE_USER = "root"
DATABASE_PASSWORD = ""
DATABASE_NAME = "migration_example"
DATABASE_MIGRATIONS_DIR = "."

準備は上記のような設定ファイルを作成するだけです!
とってもSimple!

マイグレーションファイルを作成する

$ db-migrate --create {Migration名(e.g. create_table_users)}

マイグレーションを実行する

$ db-migrate

以上です!
簡単にマイグレーションを実行することができました。

実行するとDB内に__db_version__と言う名前のテーブルが作られversion管理されるようになっていきます。
--config, ---envオプションにより環境ごとに切り替えられ--migrationオプションにより指定のrevisionまでrollbackできます。

tips

メリット

  • 複数DB / envに対応している
  • simpleで導入が簡単

simple-db-migrationの一番のメリットはそのシンプルさ、導入の容易さですね!

デメリット

  • RawSQLしか使えない
  • MySQLしか対応していない
  • Auto generateのような機能はない

まとめ

sqlalchemyと高い互換性を誇りautogenerateのような画期的な機能をもつalembicと、できる限りsimpleにバージョン管理を実現するsimple-db-migrationを比較してみました。

個人的にはalembicのauto generationがEnumのサポート、Column Orderの指定ができない点が少し残念に感じました。
autogenerateでなんでも変更検知されるはず、と思い込んでいると思わぬ事故を招きそうですね...

simple-db-migrationはその点、流すスクリプトもRawSQLでできることに制約はなく、最低限の機能は揃っているので実運用だとこちらに軍配があがる気がしました。(ただしMySQLを使用している場合に限りますが)

もしalembicのautogenerateの制約でワークアラウンド等ありましたら、コメント頂けるとありがたいです。(alembicのドキュメント量すごすぎて理解が追いついていない部分もあるかと思うので...)

24
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
19