0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python(Django) x AWS 一人アドベントカレンダーAdvent Calendar 2024

Day 22

【Python】alembicでマイグレーション時に、既に存在するインデックスの作成(ix_...)が検知される場合

Posted at

概要

PythonのアプリでAlembicを利用してマイグレーション(autogenerate)していたのですが、なぜか既にあるインデックスがマイグレーションファイルに表示される(=alembicが再度作成しようとする)、という事象が発生。

原因と解決方法がわかったので紹介します。

前提

db:mysql8.0
python:3.12
alembic:1.13.2
SQLAlchemy:2.0.32

経緯

SQLAlchemyのモデル定義には以下のように記載していました。

type_id = Column(Integer, primary_key=True, index=True)

これでmigrationファイルを生成(alembic revision --autogenerateコマンドを実行)すると、以下のように認識されていました。

sa.Column('type_id', sa.Integer(), nullable=False),

データベースを確認すると、PRIMARYという名前でインデックスが作成されています。

しかし、この状態で別のモデル定義をいじってからマイグレーションファイルを生成すると、なぜか以下のようにインデックス作成が差分で表示されます。

op.create_index(op.f('ix_type_type_id'), 'type', ['type_id'], unique=False)

既にPRIMARYという名前のインデックスがあるのに、ix_type_type_idという別名でインデックス作成しようとしてくるのです。

なぜ既にあるのにAlembic側が再度生成しようとしてくるのだろう...?

原因と解決方法

結論、index=Trueとしていたのが理由でした。
以下の記事に辿り着いた時に原因がわかりました。

おそらく、MySQLなどのDB側で主キーに対してインデックスを作成してくれるのに、Alembicのマイグレーションでもインデックス作成するように指示してしまっているため、このように重複する事象が発生したと考えられます。

よく見ると、元々あった(MySQL側のもの?)インデックスにはユニーク制約があって、後で生成された(Alembic側?)インデックスにはユニーク制約がありませんでした。他は、上述の名前以外に違いはありませんでした。

つまり、Alembic側が「あれ、私が知っているインデックス名のものがないな...」と判断して、よしなに作成してくれたのではないか、ということです。

ということで、以下のようにSQLAlchemyのモデル定義からindex=Trueを外せば、今後Alembicマイグレーション時に差分表示されないようになりました。

type_id = Column(Integer, primary_key=True)
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?