Photo by Nathan Dumlao / Unsplash
Background
因為有多個專案要用到同一個資料庫的需求. 但開發人員又彼此沒有很同步. 所以才有把資料庫獨立出來的需求. 那獨立出來還是希望他有migration的功能. 才有了這篇文章. 以下的DB以postgres為例.
Installation
$ pip3 install alembic
$ alembic init alembic
完成後會產生下列檔案:
- alembic.ini: 設定資料庫連線的相關設定, e.g. sqlalchemy.url = postgresql://user:password@host/dbname
設定好alembic.ini我們便可以繼續下去.
Start
開始建立我們第一個revision.
$ alembic revision -m "create user table"
Generating /Users/taiker/workspace/alembic/alembic/versions/41cf3ebffbf4_create_user_table.py ... done
41cf3ebffbf4
為revision id.
$ alembic edit head
介紹一下這個指令, 通常我很懶, 懶到不想去複製revision id. 所以我都會利用 alembic edit 來幫助我編輯revusion檔. (head表示為最新的revision id的意思, 你也可以把head換成你想要的
revision id).
接著我們來看一下裡面檔案長什麼樣子.
/alembic/versions/41cf3ebffbf4_create_user_table.py
"""create user table
Revision ID: 41cf3ebffbf4
Revises:
Create Date: 2018-03-11 14:40:36.370365
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '41cf3ebffbf4'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
pass
def downgrade():
pass
其實跟 Flask-Migrate 出來的檔案長蠻像的. 但還是稍微解釋一下, revision & down_revision. 這是你目前的revision_id & 你之後如果想要 revert 回去你需要對訂哪一個revision_id. (那目前down_revision=None是因為他是第一個revision檔)
upgrade() & downgrade() 分別就是你希望升級後DB長什麼樣子的script & 如果你之後DB要復原你需要透過什麼樣的script來還原DB目前的樣子.
舉個例子:
def upgrade():
op.create_table(
'user',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('name', sa.String(50), nullable=False),
sa.Column('gender', sa.Integer, nullable=False),
)
def downgrade():
op.drop_table('user')
- upgrade(): 我需要創造一個Table叫user. 裡面包含我所需要的columns.
- downgrade(): 我要復原到現在DB的架構. 那就把這個user的table給drop掉即可.
完成script之後我們需要透過指令來讓我們寫好的script對DB進行動作
$ alembic upgrade head
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 41cf3ebffbf4, create user table
透過上述的指令可以看到最新的revision檔裡面的upgrade fun已經被執行. 這時候你可以去check你的DB有沒有完成這個動作. 可以看到多了一個user table
basic=# \dt public.*
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+--------
public | alembic_version | table | taiker
public | user | table | taiker
basic=# \d user
Table "public.user"
Column | Type | Collation | Nullable | Default
--------+-----------------------+-----------+----------+----------------------------------
id | integer | | not null | nextval('user_id_seq'::regclass)
name | character varying(50) | | not null |
gender | integer | | not null |
Indexes:
"user_pkey" PRIMARY KEY, btree (id)
那接著我們來測試 downgrade 指令
$ alembic downgrade -1
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running downgrade 41cf3ebffbf4 -> , create user table
透過上述的指令可以看到最新的revision檔裡面的downgrade fun已經被執行. 一樣check一下DB
basic=# \dt public.*
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+--------
public | alembic_version | table | taiker
(1 row)
這樣你就可以運行 Alembic 的基本功能了, enjoy it.