转自:http://blog.csdn.net/oranyujian/article/details/48464365
使用Alembic迁移数据库
Alembic是SQLAlchemy作者编写的Python数据库迁移工具。我打算用它实现模型类和数据库的同步更新,就先看了些资料,学习如何实现该功能。
1. 安装
我在virtualenv下直接通过pip安装,会自动安装依赖包SQLAlchemy、Mako和MarkupSafe。
pip install alembic
SAE python环境中只需安装Mako,其他两个均为内置模块。
安装完成后就可以使用alembic命令,所有Alembic操作均由该命令实现(感觉类似Git)。
2. 初始化
需要为alembic初始化,这将创建一个alembic.ini配置文件和一个alembic“档案”目录。在合适的位置运行
alembicinitYOUR_ALEMBIC_DIR
我在模块包目录下创建目录alembic_database,目录结构如下:
myproject /| -- index . wsgi| -- . . .| -- myapp /| -- __init__ . py| -- . . .| -- alembic . ini # 配置文件| -- alembic_database /| -- env . py # 运行alembic会加载该模块| -- script . py . mako # 迁移脚本生成模板| -- . . .| -- versions / # 存放迁移脚本,类似历史库| -- . . .
3. 创建模型类
创建一个使用SQLAlchemy定义数据库的模块,比如下面这种
from myapp import dbfrom sqlalchemy . schema import Sequence as SequenceROLE_USER = 0ROLE_ADMIN = 1 # use?class User ( db . Model ) :id = db . Column ( db . BigInteger ( 64 ) , Sequence ( 'id_seq' ) , primary_key = True )uid = db . Column ( db . BigInteger ( 64 ) , unique = True )info = db . Column ( db . Text ( ) )update_time = db . Column ( db . DateTime ( ) )create_time = db . Column ( db . DateTime ( ) )def __init__ ( self , uid , info ) :self . uid = uidself . info = infodef __repr__ ( self ) :return '' % self .uid
上面例子中定义一个表user。
4. 修改配置文件
在alembic.ini中设置数据库连接
sqlalchemy . url = driver : / /user :pass @localhost /dbname
为了使用模型类更新数据库,需要在env.py中设置,将target_metadata赋值成数据库的元数据(metadata)。原有配置如下
target_metadata = None
可修改为
import osimport sysroot = os.path . dirname ( __file__ ) + '/../../' # 定位到project根目录print rootsys . path . append ( root )from myapp import dbtarget_metadata = db .metadata
自此,alembic将可以获取模型模块中定义的信息。
5. 创建版本
用 alembic revision -m+注释 创建数据库版本。由于我提供了模型类,所以可以用–autogenerate参数自动生成迁移脚本。运行
alembic revision -- autogenerate -m "create
显示
INFO [ alembic . migration ] Context impl MySQLImpl .INFO [ alembic . migration ] Will assume non - transactional DDL .INFO [ alembic . autogenerate ] Detected added table 'user'Generating (省略 ) myapp \ alembic_database \ versions \ 1c02a7117955_create_user_table.py...done
生成的数据库迁移脚本如下:
"""create user tableRevision ID: 1c02a7117955Revises: NoneCreate Date: 2013-08-30 01:03:51.703000"""# revision identifiers, used by Alembic.revision = '1c02a7117955'down_revision = Nonefrom alembic import opimport sqlalchemy as sadef upgrade ( ) :### commands auto generated by Alembic - please adjust! ###op . create_table ( 'user' ,sa . Column ( 'id' , sa . BigInteger ( ) , nullable = False ) ,sa . Column ( 'uid' , sa . BigInteger ( ) , nullable = True ) ,sa . Column ( 'info' , sa . Text ( ) , nullable = True ) ,sa . Column ( 'update_time' , sa . DateTime ( ) , nullable = True ) ,sa . Column ( 'create_time' , sa . DateTime ( ) , nullable = True ) ,sa . PrimaryKeyConstraint ( 'id' ) ,sa . UniqueConstraint ( 'uid' ))### end Alembic commands ###def downgrade ( ) :### commands auto generated by Alembic - please adjust! ###op . drop_table ( 'user' )### end Alembic commands ###
两个函数用于数据库的升级和降级。
6. 更新数据库
升级数据库使用alembic upgrade,降级使用alembic downgrade。更新到最新版
$ alembic upgrade headINFO [ alembic .migration ] Context impl MySQLImpl .INFO [ alembic .migration ] Will assume non - transactional DDL .INFO [ alembic .migration ] Running upgrade None -> 1c02a7117955 , create user table
查看数据库,发现已经创建user表。还有一个表叫做alembic_version,只有一个字段和一个值version_num,记录当前的数据库版本。
我在SAE Python本地开发环境中使用遇到问题,代码中使用pylibmc库,但SAE Python本地开发环境用sae.memcache模块代替pylibmc模块,dev_server.py中有下面的代码
import sae . memcachesys . modules [ 'pylibmc' ] = sae .memcache
直接使用pylibmc在dev_server.py下没有问题,但运行alembic程序时则会提示找不到该模块。为了解决这个问题,我判断是本地开发环境还是线上开发环境,分别载入不同的库。
if app . config [ 'ONLINE' ] :import pylibmcelse :import sae . memcache as pylibmc
参考
alembic官方教程 http://alembic.readthedocs.org/en/latest/tutorial.html
《Alembic 简明教程》http://huangx.in/18/alembic-simple-tutorial
《使用alembic》 使用alembic - 李海珍的个人页面 - OSCHINA - 中文开源技术交流社区
sqlalchemy-migrate 另一款适用于SQLAlchemy的数据库迁移工具
问题
SAE线上环境使用的SQLAlchemy版本为0.7.10,使用Alembic时出现如下错误:
AttributeError : 'MetaData' object has noattribute 'schema'
似乎对MetaData的支持不够,版本号过低。升级成0.8.5,就可以正常使用。
重新生成脚本
我使用Alembic时,已经使用SQLAlchemy建立初始模型的数据表,不是从零开始,所以无法使用Alembic完整迁移数据库。所以,我使用Alembic重新生成数据库迁移脚本。
Alembic在数据库中仅保存当前版本号,其余信息均从文件读取。删除历史记录,只需要将数据库表删除,并删除versions下的所有文件。而alembic.ini和env.py中的设置无需更改,可以再次使用。
[转载:http://windrocblog.sinaapp.com/?p=940]