Golang Migration
一个项目长期运行,一定设计到数据库表的迭代升级,尤其是在多环境交付的模式下,清晰严格的版本数据库设计升降机管理显得尤为必要。在go语言下有相关工具go migration来完成相关工作。
go migration 可以做什么
- 管理版本sql
- 将db table升级到指定版本
- 将db table降级到指定版本
- 支持mysql,postgresql, sqlLite, MariaDB, MongoDB等主流数据库
- 支持命令行与SDK两种执行方式
安装
git clone git@github.com:golang-migrate/migrate.git
cd migrate; make build
mv migrate /usr/local/bin
使用介绍
创建版本sql
migrate create -ext sql -dir database/migration/ -seq init_mg
- -ext 文件格式
- -dir sql目录
- -seq 序列号
版本格式如下
- 000001_init_mg.up.sql // 1版本的升级sql
- 000001_init_mg.down.sql // 1版本的降级sql
执行变更到DB
升级到最新版
migrate -path database/migration/ -database "mysql://{user}:{passwd}@localhost:3306/{dbname}" -verbose up升级N个版本
migrate -path database/migration/ -database "mysql://{user}:{passwd}@localhost:3306/{dbname}" -verbose up {N}降级N个版本
migrate -path database/migration/ -database "mysql://{user}:{passwd}@localhost:3306/{dbname}" -verbose down {N}直接升降级到指定版本
migrate -path database/migration/ -database "mysql://root:123456@tcp(127.0.0.1:3306)/vc" -verbose goto 2
migration的实现逻辑如何
在官方的介绍里,有一张图如下。就是这么简单
在使用migrate的过程中,用户做的事情是
- 创建版本sql文件,文件名格式符合migrate格式
- 维护版本之间的升降级sql
migrate做的事情是
- 按照文件名识别sql的版本序列
- 按照用户预期的目标版本顺序执行升降级sql
- 将当前的sql版本记录在服务db的schema_migrations表中
总结
migration的实现思路并不复杂,工具的目标是协助解决版本迭代时sql升降级顺利。
golang migration使用文件名来识别版本,当一个版本sql变更较多时可能导致sql文件臃肿。其他类似服务有些支持以目录为版本粒度,对sql较多的大型项目更加友好。
migration只是一个执行器,软件的sql升降级实际能否顺利最终依赖up.sql和down.sql的维护策略,对于良好的维护策略应该做到以下几点
- sql的重入考虑,create table / drop table 时判断table是否存在
- 对历史版本 只读特性 的严格支持
- 对于多db实例的sql语法兼容
- 对于删改操作的谨慎执行,可以考虑软删除策略
- migration 需要从sql to db, 要保持to db的链路唯一,不要再使用其他的to db链路,比如model to db