之前做过一个数据库的工具,可以从数据库中抽取所有应用关心的信息,包括表结构、分区、索引,存储过程,函数,序列,常量参数,技术配置表的内容等。有了这些信息可以检查确保环境配置的正确性,另外也便于开发人员检索使用。近期计划在组内搭建数据库变更脚本的自动部署及管理工具,进一步提高数据库变更的效率,保证变更的正确性。目前此类开源工具有很多,我们最终决定使用Flyway,它在Java项目中很常用,它可以批量对数据库脚本进行部署,并会对当前数据库环境的部署情况进行记录跟踪。
Flyway工具使用简单,它提供了Java API、Maven插件、命令行等多种使用方式,这些具体的使用方式在此就不详细介绍了,大家可以参阅“Flyway 官方文档”。下面结合我项目的特点来介绍下Flyway的使用,也欢迎大家批评指正。
我们项目本身比较复杂,主要体现在下面几个方面:
- 从数据库角度整体分为联机数据库、批量数据库,对于特殊产品还会有其他数据库服务器,例如信息报告数据库、第三方支付数据库(主库、多个子库)、海外业务数据库(多个)等;
- 从测试环境上分为单元测试环境、PL1-PL4共4个应用组装测试环境、VT环境、生产环境,这些不同环境之间的表空间,数据库个数也有差异;
- 多个时间点的版本会并行进行开发测试,不同版本的测试环境也不同,且同一个测试环境的版本可能会出现跳跃。
众所周知,不同环境的数据库要尽量保持一致,这样在维护方面会简单很多,但有些差异是很难避免的。为了更好的解决不同环境的差异我们设计了一套模板体系,只需要上传一套sql变更脚本,然后通过程序来生成不同环境的特定脚本,便于部署。另外此程序还会完成变更脚本的比对工作,并输出比对结果,从而保证模板和具体环境脚本的一致性。具体程序代码见FlywayMigration Git,大家可以自由使用,后续此程序的功能还会继续完善。
目前我们的sql变更脚本的目录结构如下:
+ dbscript
|- ljdb // 联机数据库
|- baseline //存储当前数据库的基线信息
|- common //所有环境通用的信息
|- 20170819 //按版本建立不同的目录
|- 20170922
|- template //模板信息
|- 20170819 //按版本建立不同目录
|- 20170922
|- unit //单元测试
|- xxx //目录下内容会自动生成
|- vt
|- template-config.yml
|
+- pldb //批量数据库
|-xxx //同ljdb
其中template目录下是按照版本保存的模板文件,unit、vt等特定环境目录是程序自动生成的,且不允许手工维护。
通过上面的做法可以很好的做到对环境差异的屏蔽。对于第三个版本跳跃的问题目前没想到好的方法,目前想到的方法是通过不同版本使用不同的非交叉版本号,当版本跳跃时设置Flyway允许不校验执行顺序,另外通过最开始提到数据库信息抽取工具对变更结果进行比对,从而保证正确性。
这里有个小故事想和大家分享下:最开始在安排脚本目录结构时计划将template、unit、vt等特定环境的目录放在版本点如20170819的目录下,以便同一个版本的所有变更脚本都在一起,便于维护,目录结构类似ljdb/20170822/common、unit、vt、template这样。这样一来针对某个环境部署sql脚本时就需要根据环境名称来过滤需要的脚本,例如对于unit单测环境同时需要ljdb/*/common+unit多个版本点的目录。在网上找了很多地方,发现flyway不支持这种路径过滤方式,只能把多个版本点的路径通过程序一一列举,这样体验很差,而且容易出现sql脚本部署的遗漏。官方对此的说法是通过调整目录结构来解决。当时还觉得不爽,现在回头看调整目录结构后反而觉得更清爽了。站在这个角度官方的做法反而很值得推崇,不提供不必要或者容易误用的功能。