目录
功能:数据库脚本迁移工具
使用场景:
- 本地数据库开发模式下,开发人员A对数据库表结构进行了修改,并修改了对应的dao层的代码,开发人员B更新了A的代码,确没有运行对应的对应的数据库脚本就会导致程序报错。
- 项目上线、者项目部署或者项目更新时,也需要维护人员去运行大量的数据库脚本。
使用方法:
把SQL脚本放在resource/db/migration文件夹下,应用会在启动时自动根据flyway_schema_history【应用第一次集成flyway时生成】的执行情况自动辨别并执行脚本
开始使用
1. pom
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.2.4</version>
</dependency>
2. yml配置
这些配置都可以在org.flywaydb.core.api.configuration
中可以看到
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springclouddemo?useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
flyway:
# 是否启用flyway
enabled: true
## 编码格式,默认UTF-8
encoding: UTF-8
## 迁移sql脚本文件存放路径,默认db/migration
locations: classpath:db/migration
## 迁移sql脚本文件名称的前缀,默认V
sqlMigrationPrefix: V
## 迁移sql脚本文件名称的分隔符,默认2个下划线__
sqlMigrationSeparator: __
# 迁移sql脚本文件名称的后缀
sqlMigrationSuffixes: .sql
# 迁移时是否进行校验,默认true
validateOnMigrate: true
# 设置为true,当迁移发现数据库非空且存在没有元数据的表时,自动执行基准迁移,新建schema_version表
baselineOnMigrate: true
3. 在resource下新建db/migration文件夹,把数据库脚本放进去
4. 在应用启动时执行SQL脚本
命名规范
-
V文件:V版本号__版本描述.sql
V文件只会在同一个数据库执行一次
例如:R2020.04.06__新增times字段.sql -
R文件:R版本号__版本描述.sql
文件内容发生改变时就会被执行,执行顺序是在所有V文件执行完之后执行,因为每次内容发生改变时执行,所以编写DDL语句时需加上CREATE OR REPLACE。
注意事项:
版本号必须唯一.
必须拥有数据库root账号权限。在5.2.2版本之后,flyway需要访问
performance_schema.user_variables_by_thread
,但是普通用户并没有相关权限,flyway的后续功能用不了。遇到次问题将flyway版本更换到5.2.1就好了应用会在启动时生成
flyway_schema_history
,但如果此时已经集成了druid的并开启sql防火墙的话,druid会把生成该表的语句当成SQL注入
过滤掉,因此需要在应用启动前先手动执行SQL。SQL脚本如下
DROP TABLE IF EXISTS `flyway_schema_history`;
CREATE TABLE `flyway_schema_history` (
`installed_rank` int(11) NOT NULL,
`version` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`script` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`checksum` int(11) NULL DEFAULT NULL,
`installed_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`installed_on` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`execution_time` int(11) NOT NULL,
`success` tinyint(1) NOT NULL,
PRIMARY KEY (`installed_rank`) USING BTREE
) ENGINE = InnoDB
或者在jar包中也能找到这条语句
报错解决
报错内容如下
ERROR: Validate failed:
Migration checksum mismatch for migration version 1
-> Applied to database : 625057440
-> Resolved locally : 1715188512
这种报错的指的是原有的checksum值和本次执行的checksum值对应不上,也就是数据不完整,就是flyway_schema_history
中的记录在当前的存放脚本文件夹中不完整,
复现:
此时记录表中只有一条数据。
文件夹中只有一个脚本。
这时我把原来的脚本删了,同时新增另外一个脚本,注意不要flyway_schema_history
中的记录,这时执行迁移就会报刚才的错误。
报错:FlywayException: Validate failed: Detected resolved migration not applied to database
原因:
flyway执行升级脚本是按版本号升序依次执行的, 如果版本号为201908080001__add_table.sql的脚本已经被执行了, 这时执行版本号小于该脚本的, 如201908060001__add_table.sql, flyway会抛出该异常
解决办法:修改版本号使大于当前版本号。
flyway使用过程中遇到的问题
-
大部分问题都是脚本校验不通过的问题,建议先把确保数据库脚本能运行无误,确保 * t_sys_schemas_version*中没有当前版本的运行记录。版本号一定不能相同,且要大于最新版本号
-
由于我们使用了shiro,且shiro中的过滤器是存在数据库中的,在应用启动的时候将过滤器链注入到shiro中,flyway脚本中也有一些新增加的过滤器链的配置,但是由于shiro是先于flyway执行,会导致shiro注入的过滤器链不完整,所以要使用CommonLineRunner 在应用启动后重新加载过滤器链。
-
解决方案:
方案一: 手写flyway配置执行类,设置执行顺序最先执行根据启动配置文件是否执行SQL迁移,dev环境不执行SQL迁移. 方案二: 手写flyway配置执行类 @DependsOn("flywayConfig") // 这里指定依赖于 flywayConfig 类 方案三 启动完成后重新加载过滤器链