迁移之前,需先 确认哪些迁移已经应用到数据库了。查看应用到数据库的最后一次迁移ID 用 alembic current,
(venv) D:\alchemy\c11>alembic current
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
0bad48b33ec2 (head) #指出当前的迁移
alembic history 显示 历史迁移记录。
(venv) D:\alchemy\c11>alembic history
9f5bb26a626e -> 0bad48b33ec2 (head), rename cookies
87eea99e5889 -> 9f5bb26a626e, add cookie model
<base> -> 87eea99e5889, emptyinit
迁移降级(撤销)。downgrade + ID
(venv) D:\alchemy\c11>alembic downgrade 9f5bb26a626e
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running downgrade 0bad48b33ec2 -> 9f5bb26a626e, rename cookies
降级以后,发现 数据库里表的名称恢复了。
(venv) D:\alchemy\c11>sqlite3 alembictest.db
SQLite version 3.35.5 2021-04-19 18:32:05
Enter ".help" for usage hints.
sqlite> .tables
alembic_version cookies
查看数据库所处的迁移级别(ID):
(venv) D:\alchemy\c11>alembic current
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
9f5bb26a626e #但这次的没有head了
现在数据库回到了指定的迁移。但如果想让app恢复到工作状态,还要把db.py里的 表名 从new_cookies改回来cookie,以便使用。
(venv) D:\alchemy\c11>alembic history
9f5bb26a626e -> 0bad48b33ec2 (head), rename cookies
87eea99e5889 -> 9f5bb26a626e, add cookie model
<base> -> 87eea99e5889, emptyinit
(venv) D:\alchemy\c11>alembic current
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
9f5bb26a626e
调用history和current发现,head不在目前的迁移(或者说我们不在最新的迁移里)。如果不处理,下次使用alembic upgrade head时会,new_cookies迁移就会运行,导致 报错。最简单的处理办法是:把不要的迁移的直接在alembic/versions/ 目录里删掉。
标记数据库迁移级别stamp。
当要执行 跳过迁移 或 恢复数据库 等操作时,数据库可能会认为 迁移 和 实际情况不同。为了解决这个问题,我们用stamp 强行 把数据库标记成 某个级别的迁移,但实际上 并没有运行这个迁移。它只是更新了 alembic表,以反映我们在命令中强制 标记的迁移级别(ID)。也就是实际上 跳过了这个迁移。
像现在我们在9f5bb26a626e,数据库里的表 名称也恢复成 cookies了,但我就想把迁移标记成new_cookies时的0bad48b33ec2
(venv) D:\alchemy\c11>alembic stamp 0bad48b33ec2
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running stamp_revision 9f5bb26a626e -> 0bad48b33ec2
执行current发现 现在的迁移级别就是0bad48b33ec2,但数据库里 表 名称还是9f5bb26a626e的cookies
(venv) D:\alchemy\c11>alembic current
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
0bad48b33ec2 (head)
(venv) D:\alchemy\c11>sqlite3 alembictest.db
SQLite version 3.35.5 2021-04-19 18:32:05
Enter ".help" for usage hints.
sqlite> .tables
alembic_version cookies
sqlite>
也就是没有运行0bad48b33ec2。跳过了0bad48b33ec2。
像这样用stamp,只适用于当前的数据库。如果改了alchemy.ini的sqlalchemy.url,Alembic迁移环境 指向了另一个数据库,而新数据库又 低于跳过的迁移的级别 或者为 空。那可以用alembic upgrade head真正运行这个迁移。
这时候如果还想降级回9f5bb26a626e,会因为数据库里没有new_cookies表而报错。
(venv) D:\alchemy\c11>alembic downgrade 9f5bb26a626e
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running downgrade 0bad48b33ec2 -> 9f5bb26a626e, rename cookies
Traceback (most recent call last):
...
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: new_cookies
[SQL: ALTER TABLE new_cookies RENAME TO cookies]
可以stamp回去
(venv) D:\alchemy\c11>alembic stamp 9f5bb26a626e
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running stamp_revision 0bad48b33ec2 -> 9f5bb26a626e
(venv) D:\alchemy\c11>alembic current
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
9f5bb26a626e
处理掉0bad48b33ec2。在version里直接把迁移文件删除。再次用current查看状态,head在目前的迁移,9f5bb26a626e是最新的迁移。
(venv) D:\alchemy\c11>alembic current
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
9f5bb26a626e (head)