数据库迁移工具Flyway

不管是在开发过程中还是在线上,数据库结构都是经常变化的,很多情况下都需要对数据库的变化做跟踪和管理,Flyway就是这样一款管理工具。

在Flyway里,每次数据库变化都称为一次迁移,每次迁移都有一个版本号。Flyway会在数据库里存储当前处在哪个版本。每当需要上线的时候,你可以手动或者自动地将代码里的多个迁移,同步到数据库当中。

迁移的规则

如图所示,文件名以V开头,后面跟上版本号,然后是两个下划线,最后是对此次迁移的描述,用下划线或者空格隔开。在每个sql文件中,都可以写多个DDL语句或者CRUD语句,根据你的需求而定。

怎么才能触发迁移呢?Flyway提供了多种方式:

我主要用的是最后一种方式,在Spring Boot中使用。Spring Boot自带对Flyway的支持,如果你的项目引入了Flyway的依赖,Spring Boot会自动将其配置好。Flyway的默认迁移文件路径是上图里的类路径 db/migration 。相对于前两种方式,使用API可以不用安装命令行工具,不用新建配置文件(使用Spring Boot的配置文件),同时他还可以利用项目里的DataSource对象,做到了开箱即用。

Flyway的工作原理

当Flyway第一次运行的时候,他会在你的数据库里新建一张表flyway_schema_history,这个表里记录了每个迁移的信息,比如说版本号、说明、对应的SQL文件名,执行日期和是否执行成功等等。

表结构

当Flyway再次运行的时候,会在应用启动的时候扫描db/migration目录,再读取flyway_schema_history表,看看哪些迁移是新增的,需要去执行。新增的迁移会根据版本号依次执行。

执行某个迁移的时候,你可能写了好多语句,Flyway会把这些语句放到一个事务里,当出错的时候,会回退。但是,很多数据库是不支持把DDL放到事务里的,你得查查你用的数据库是否支持(除了PostgreSQL还有谁?)。如果数据库不支持,而你的迁移过程又出错了的话,很可能不能进行干净的回退,导致你需要手动去清理。

除了SQL还可以写Java

大多数迁移只需要SQL就可以完成了,但是针对复杂的场景,比如字段内容要根据业务来修改,这个时候就需要写代码了,幸运的是Flyway也支持用Java来完成迁移,Java类型的迁移命名规则上面提到的一样,也需要放到类路径 db/migration 下:

Java迁移需要继承BaseJavaMigration

可惜的是,Flyway并没有官方支持将Java迁移类实例化成Spring容器里的对象,所以没有办法通过@AutoWired将你现成的组件包含进来。

Flyway的问题

对于已经执行过了的迁移,你就不能再对其进行更改了,否则会报错。比如你的迁移改了个表名,但是之后如果你想换一个表名,那就需要新建一个迁移。

如果是个人进行开发,这个没问题,但是如果涉及到团队协作,就有问题了。比如两个同事可能在不同的分支都新建了迁移,不管是谁合并到主分支,另外一个人的分支肯定受影响。当然这不是什么大的问题,总有办法可以解决,况且只影响开发环境,开发者拉取主分支之后,发现和自己的有冲突,那就把自己的迁移版本号改一下,清空数据库重新运行就行。

在老项目中引入Flyway

当然你可以可以选择当产品稳定之后,再引入Flyway来尽量避免上面说到的问题。这种情况下稍微麻烦一点,官方文档也做了说明。

你首先需要将线上环境的数据库结构(DDL)导出,保存到db/migration目录下,作为项目的第一个迁移,文件名改成类似V1__Init_db.sql这种。随后利用flyway命令的baseline方法,在生产环境生成flyway_schema_history表,自动在表里把V1__Init_db.sql的状态设置为执行成功,实际上没执行。这一番操作过后,数据库就纳入了Flyway的管理,以后数据库结构有变化,直接编写迁移文件就行。当然你在开发过程中需要重建数据库的时候,V1__Init_db.sql还是会执行到的。

总结

Flyway还是值得一试的,项目小的时候使用Flyway,项目大了可以逐渐过渡到由DBA负责数据库迁移等相关操作。另外Flyway还提供了一些付费的商业特性,有需要的可以看看。

参考资料

发表评论

电子邮件地址不会被公开。