轻松上手数据库版本管理工具Flyway
Flyway是一个用Java编写的开源数据库版本管理工具,或者说是数据库结构变更工具,旨在帮助开发和运维更容易地管理数据库演进过程中的各个版本。它的源代码在github上。
简介
在开发过程中,数据库是不断向前演进的,可以说是拥有“版本”这个概念。通常当在生产环境部署新代码的时候,会由开发或者DBA来做数据库结构变更的操作。当数据库较小,环境数量少的时候,人工操作比较有把握,直接就人肉来做结构变更了。可要是在数据库复杂、环境数量多(开发、测试、预发布、生产……)的情况下,人工处理这样的事就开始有些令人担心了。如何保证所有环境的数据库结构是一致的?如何知道当前环境的数据库是哪个状态?如何知道生产环境的一个关于数据库的hotfix是否也在预发布环境中执行了?Flyway就是用来解决这样的问题的工具。它的原理非常简单,就是在数据库中创建一张自己用的表,例如schema_version,在里面存放数据库当前的状态,以此来管理数据库的版本。Flyway提供了命令行、API、Maven、Gradle、Ant、SBT等各种方式,来让我们更容易将其与自己的项目结合。类似的工具还有Liquibase、dbdeploy等。
本文将会用Docker来创建一个mysql的实例,用Maven来创建一个包含数据库的Java项目,并使用Flyway来进行版本管理。
准备环境
首先请自行安装Docker、Java、Maven和喜欢的IDE。我用的是Intellij IDEA社区版。我用Vagrant启动了一台已经安装过Docker的Ubuntu虚拟机,它的IP是192.168.33.88
,可以用以下命令来直接启动mysql容器来提供数据库服务并创建ggg数据库:
接下来新建一个Maven工程helloFlyway:
在helloFlyway/pom.xml
里加入flyway的maven插件和mysql-connector-java的依赖(别忘了根据你自己的数据库来配置jdbc):
接下来创建一个数据库版本1的文件:
工程创建好并用intellij导入后,应该是这样的:
版本管理
使用以下命令来运行flyway:
出现BUILD SUCCESS就说明数据库结构变更已经完成了。我们可以登录到数据库看一看:
运行以下sql就可以看到flyway确实已经起作用了:
而表schema_version里面也有了一条记录。接下来再创建一个数据库版本2的文件:
再次用同一条命令来运行flyway:
就会看到日志里显示Current version of schema `ggg`: 1和Migrating schema `ggg` to version 2 - Add people。如果我们重复运行mvn flyway:migrate
,就会看到Schema `ggg` is up to date. No migration necessary。现在查看一下两张表:
PERSON表里已经有了V2__Add_people.sql
里的三条记录,而schema_version表里,就可以看到现在的版本为2。通过这样的方式,就可以管理数据库的版本了。
历史数据库
如果数据库里已经有历史数据了,那就会稍微麻烦一点儿。我们来试试看,首先改造一下ggg数据库:
这样一来,数据库的版本便被清空,PERSON表也变成了STUDENT表。如果直接运行mvn flyway:migrate
会报错:org.flywaydb.core.api.FlywayException: Found non-empty schema `ggg` without metadata table。这时候需要用到另一个命令:
上面的baseline
命令会以现在的数据库结构为基础,创建一张schema_version表,标明现在的版本是1。接着运行mvn flyway:migrate
还会报错:Migration of schema ggg
to version 2 - Add people failed。这是因为数据库现在是版本1,所以会忽略V1__Create_person_table.sql
而直接执行V2__Add_people.sql
,而V2__Add_people.sql
依赖于V1__Create_person_table.sql
里创建的PERSON表,所以失败了。解决的方法也很简单,改变两个sql文件的版本即可:
Flyway的命名规范如下:以V
开头,.sql
结尾,版本号可以使用.
或者_
,版本号和描述之间用两个下划线__
分开。要是执行成功,但是却看不到PERSON表,那很可能是因为schema_version表里的版本已经是一个错误的版本2了,运行repair之后再重新migrate即可:
其它
Flyway认为没有必要支持回滚。可以通过mvn flyway:info
命令来查看数据库的版本和和需要执行的sql脚本。通过mvn flyway:clean
来清空数据库,这条命令对于测试很方便,但是千万要小心生产环境!!!此外,还有一个较常用的命令:mvn flyway:validate
可以验证是否所有的sql都已经在数据库上运行完毕了。