7

月光中的污点 | Flyway 简单入门教程

 3 years ago
source link: https://www.extlight.com/2019/09/11/Flyway-%E7%AE%80%E5%8D%95%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Flyway 是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式。Flyway 可以独立于应用实现管理并跟踪数据库变更,支持数据库版本自动升级,并且有一套默认的规约,不需要复杂的配置,Migrations 可以写成 SQL 脚本,也可以写在 Java 代码中,不仅支持 Command Line 和 Java API,还支持 Build 构建工具和 Spring Boot 等,同时在分布式环境下能够安全可靠地升级数据库,同时也支持失败恢复等。

二、简单介绍

2.1 主要特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
普通 SQL:纯 SQL 脚本(包括占位符替换)没有专有的XML格式,没有锁定

无限制:使用 Java 代码来进行一些高级数据操作

零依赖:只需运行在 Java6(及以上)和数据库所需的 JDBC 驱动

约定优于配置:迁移时,自动查找系统文件和类路径中的 SQL 文件或 Java 类

高可靠性:在集群环境下进行数据库升级是安全可靠的

云支持:完全支持 Microsoft SQL Azure, Google Cloud SQL & App Engine、Heroku Postgres 和 Amazon RDS

自动迁移:使用 Flyway 提供的 API,让应用启动和迁移同时工作

快速失败:损坏的数据库或失败的迁移可以防止应用程序启动

数据库清理:在一个数据库中删除所有的表、视图、触发器,而不是删除数据库本身

2.2 运行原理

当 Flyway 连接数据库中的 schema 后,会先检查是否已存在 flyway_schema_history 表,如果没有则创建。该表用于跟踪数据库的状态,如数据迁移的版本,迁移成功状态等信息。

flyway_schema_history 存在后,Flyway 会扫描文件系统或应用中的 classpath 目录的数据迁移文件,然后根据它们的版本号进行按序迁移,如下图:

flyway-03.jpg

flyway_schema_history 表记录的内容如下:

installed_rank version description type script checksum installed_by installed_on execution_time success 1 1 Initial Setup SQL V1__Initial_Setup.sql 1996767037 axel 2016-02-04 22:23:00.0 546 true 2 2 First Changes SQL V2__First_Changes.sql 1279644856 axel 2016-02-06 09:18:00.0 127 true

由于 flyway_schema_history 表中记录了迁移的版本号,如果文件的版本号小于或等于标记为当前版本的版本号,则忽略它们不执行。

上边描述的内容或许对读者来说还不够直观,那么下面我们就开始进行实战演练。

测试环境:Mysql5.7

新建一个 Maven 项目。

3.1 添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
<!-- flyway -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.2.4</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>

3.2 配置数据迁移文件

在项目的 src/main/resources 下创建 db/migration 目录,该目录下放置需要数据迁移的文件。

数据迁移文件名称格式为:V[version]__[name].sql

注意:名称中[version]和[name]之间是两个下划线!

本次测试新建名为 V1__Create_person_table.sql 的文件,内容如下:

1
2
3
4
create table PERSON (
ID int not null,
NAME varchar(100) not null
);

版本 1 数据迁移的内容是创建一张 PERSON 表。

3.3 编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class FlywayTest {

public static void main(String[] args) {
String url = "jdbc:mysql://127.0.0.1:3306/flyway?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false&serverTimezone=GMT%2B8";
String user = "root";
String password = "tiger";
Flyway flyway = Flyway.configure().dataSource(url, user, password).load();

// 创建 flyway_schema_history 表
// flyway.baseline();

// 删除 flyway_schema_history 表中失败的记录
// flyway.repair();

// 检查 sql 文件
// flyway.validate();

// 执行数据迁移
flyway.migrate();

// 删除当前 schema 下所有表
// flyway.clean();
}
}

执行结果如下图:

flyway-01.gif

图中,数据库 flyway 中创建了 flyway_schema_history 表和 PERSON 表,数据成功迁移到指定数据库中。

当系统升级时又需要做数据迁移,我们只需在 db/migration 目录下再放置新版本的 sql 文件即可。

比如,我们再新建一个名为 V2__Add_people.sql 文件,内容如下:

1
2
3
insert into PERSON (ID, NAME) values (1, 'Axel');
insert into PERSON (ID, NAME) values (2, 'Mr. Foo');
insert into PERSON (ID, NAME) values (3, 'Ms. Bar');

版本 2 的数据迁移内容是往 PERSON 表中插入 3 条数据。

再次执行上边的程序,演示效果图如下:

flyway-02.gif

四、Spring Boot 整合

4.1 添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

4.2 application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/flyway?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false&serverTimezone=GMT%2B8
username: root
password: tiger
flyway:
enabled: true
# 禁止清理数据库表
clean-disabled: true
# 如果数据库不是空表,需要设置成 true,否则启动报错
baseline-on-migrate: true
# 与 baseline-on-migrate: true 搭配使用
baseline-version: 0
locations:
- classpath:db/migration/mysql(根据个人情况设置)

将需数据迁移的 sql 文件放置到 db/migration/mysql 目录中,启动 Spring Boot 项目即可运行 Flyway 进行数据迁移。

测试结果同上,此处不再张贴。

注意事项:

如果 flyway 不是项目初期引入,而是在数据库已有表的情况下引入时必须设置 baseline-on-migrate: true,设置该配置启动项目后,flyway 就会在数据库中创建 flyway_schema_history 表,并且会往该表中插入一条 version = 1 的建表记录,如果迁移数据有 V1__ 开头的文件,扫描文件会忽略该文件不执行迁移,进而可能引发其他迁移数据出错的问题。

以上边的 2 个 sql 文件为例进行演示,flyway 库中已有一张 test 表,运行程序结果如下:

flyway-04.jpg

由于忽略了 V1__Create_person_table.sql ,库中就不创建 PERSON 表,在迁移 V2__Add_people.sql 文件中的数据时必然失败。

解决方案先删除flyway_schema_history 表, 然后配置文件中设置 baseline-version: 0,或修改数据迁移文件版本名称,最后再次启动应用即可。

五、参考资料

Flyway 官网

Spring Boot 文档


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK