数据库版本管理工具-flyway,集成springboot

2,958 阅读4分钟

背景

在项目开发中,程序代码可以使用svn或者git来管理版本。但是在数据库开发中,版本的控制一直是个比较头疼的问题,通过调研,spring的官方支持flywayliquibase的数据库版本管理工具

flyway

flyway 是一个敏捷工具,用于数据库的移植。采用 Java 开发,支持所有兼容 JDBC 的数据库。

主要用于在你的应用版本不断升级的同时,升级你的数据库结构和里面的数据。

官网 flywaydb.org/

支持的数据库

Oracle、SQL Server、DB2、MySQL、Aurora MySQL、MariaDB、Percona XtraDB群集、PostgreSQL、Aurora PostgreSQL、Redshift、CockroachDB、SAP HANA、Sybase ASE、Informix、H2、HSQLDB、Derby、SQLite、Firebird

flyway的工作原理

一言以蔽之:flyway通过历史记录表(flyway_schema_history)来记录版本历史。每次随项目启动时将会自动扫描在resources/db/migration下的文件并查询flyway_schema_history判断是否为新增文件。如果是新增的文件,则执行该迁移文件。如果不是,则忽略

flyway_schema_history 表结构

CREATE TABLE `flyway_schema_history` (
  `installed_rank` int(11) NOT NULL,
  `version` varchar(50) DEFAULT NULL,
  `description` varchar(200) NOT NULL,
  `type` varchar(20) NOT NULL,
  `script` varchar(1000) NOT NULL,
  `checksum` int(11) DEFAULT NULL,
  `installed_by` varchar(100) NOT NULL,
  `installed_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `execution_time` int(11) NOT NULL,
  `success` tinyint(1) NOT NULL,
  PRIMARY KEY (`installed_rank`),
  KEY `flyway_schema_history_s_idx` (`success`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

原理解析

第一次执行:在一个空数据库上执行时。会创建一个flyway_schema_history。这个表用来记录和追踪数据库版本的状态,然后flyway会扫描文件系统或者项目下classpath路径下的数据库文件

再次执行:flyway会再次扫描迁移文件,然后将迁移文的版本号与历史记录表中的版本号进行对比。flyway会忽略版本号小于等于表中当前最大版本的迁移文件,剩余待执行迁移文件会按版本号升序执行。(译者注:并非真正忽略,而是会校验checksum值是否一致,以此来保证历史版本文件未被篡改。)

springboot 集成flyway

依赖

这里可以不用指定flyway的版本号,因为springboot父类依赖中已经指定了版本号, 如果执行可能会包版本冲突

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
	</parent>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.17</version>
		</dependency>
		<dependency>
			<groupId>org.flywaydb</groupId>
			<artifactId>flyway-core</artifactId>
		</dependency>

增加配置

# 开启
spring.flyway.enabled=true
# 禁止清理数据表
spring.flyway.clean-disabled=true
# 版本控制信息表名,默认 flyway_schema_history
spring.flyway.table=flyway_schema_history
# 是否允许不按顺序迁移
spring.flyway.out-of-order=false
# 如果数据库不是空表,需要设置成 true,否则启动报错
spring.flyway.baseline-on-migrate=true
# 与 baseline-on-migrate: true 搭配使用,小于此版本的不执行
spring.flyway.baseline-version=0
# 使用的schema 这里可以不用设置,因为不设置就使用使用spring连接数据的地址和数据库
spring.flyway.schemas=test
#数据库连接
#spring.flyway.url=
#数据库用户名
#spring.flyway.user=
#数据库密码
#spring.flyway.password=
# 执行迁移时是否自动调用验证
spring.flyway.validate-on-migrate=true

实际配置

spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/renren-fast?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
            username: 
            password: 
    flyway:
        baseline-on-migrate: true
        enabled: true
        locations: classpath:db/migration
        baseline-version: 1            

增加脚本文件

在resources目录下创建db/migration文件夹

在db/migration目录下创建版本迁移文件 V1__initial.sql

命名规则

在src/resources下创建 db/migration目录,在其中创建对应的SQL文件,其中又分为不同的文件类型,基于约定由于配置的原则,通过文件命名方式进行区分

版本迁移以V开头,只会执行一次;回退迁移以U开头,一般不使用;可重复执行迁移以R开头,每次修改后都会重新执行

image

演示V开头

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for initial_monitor
-- ----------------------------
CREATE TABLE `users`  (
  id bigint not null auto_increment,
  name varchar(50) not null,
  primary key (id)
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;
)

启动工程,查看数据库 增加users表 同时flyway_schema_history有数据

image.png

演示R开头

在db/migration目录下创建版本迁移文件 R__AddUser.sql

insert into users (name) values ("test");

执行后发现user表中多了一条记录,再次执行也是只有一条记录,只有当我们修改内容后才会再次执行

insert into users (name) values ("test123");

这样表中多了一条记录

image.png

演示U开头

该版本不支持,pro版本支持,也不建议使用

总结

我们在使用flyway管理数据库版本是比较简单的,只需要按照约定好对应的版本号,就可以自动的生成,可以快速有效的管理数据库版本