一、简介1.1Flyway是哪些?
Flyway是一款开源的数据库版本管理工具,可以实现管理并跟踪数据库变更,支持数据库版本手动升级,但是不须要复杂的配置,还能帮助团队愈加便捷、合理的管理数据库变更。
例:创建两个sql变更文件,项目启动后会将两个文件中的sql词句全部执行。
1.2为何使用Flyway?
简单举个反例:开发时,假如A开发和B开发都对同一数据库进行了更改,这么怎样进行数据同步呢?如果多个开发人员都更改了sql脚本,如何同步到测试环境和生产环境?
类似于以上的情况在日常开发中不胜枚举,在最开始的单体构架中,我们公司采用了通过校准数据库版本号来实现sql的变更,这似乎就能解决大部份问题,但每次都须要维护变更sql的代码和数据库版本号,且对于后续服务上云也是非常不便的。为此我们须要对数据库校准的方案进行调整,就去督查了目前市面上比较流行的Flyway和Liquibase,综合对比出来,最终选择了Flyway作为后续的数据库版本管理工具,具体差别如下:
1.3Flyway的工作原理
Flyway在第一次执行时,会创建一个默认名为flyway_schema_history的历史记录表,这张表会拿来跟踪或记录数据库的状态,之后每次项目启动时就会手动扫描在resources/db/migration下的文件的版本号而且通过查询flyway_schema_history来判定是否有新增文件,因而判定是否进行迁移。
默认的查找migration的路径为classpath:db/migration,对应SQL文件可放置在src/main/resources/db/migration下,Java类可放置在src/main/java/db/migration下。
Flyway在第一次执行时,会创建一个默认名为flyway_schema_history的历史记录表,这张表会拿来跟
踪或记录数据库的状态,之后每次启动时就会手动扫描在resources/db/migration下的文件而且通过查
询flyway_schema_history来判定是否为新增文件,因而判定是否进行迁移。
默认的查找migration的路径为classpath:db/migration,对应SQL文件可放置在
src/main/resources/db/migration下,Java类可放置在src/main/java/db/migration下
1.3.1Flyway的校准版本号算法
flyway在升级数据库时会先估算之前早已升级过的脚本的checksum值和数据库的checkSum值进行比对,假如老脚本发生了变化后checkSum校准都会失败,因而抛出异常,checkSum估算算法为(CRC32(循环冗余校准码)算法)。
新增的脚本则会和数据库中的版本号进行比较,假如大于数据库储存的最后一个版本号,也不会继续执行。
1.3.2Flyway的锁机制
Flyway使用数据库锁机制(lockingtechnologyofyourdatabase)来协调多个节点中标linux,进而保证多套应用程序可同时执migration,但是集群控制也可做配置。基于数据库锁机制实现分布式锁有两种,基于数据库表和基于数据库排他锁,Flyway采用的是基于数据库排他锁。
排他锁(Exclusive Locks,简称X锁),又称为写锁、独占锁,在数据库管理上,是锁的基本类型之一。若
事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放
A上的锁。这就保证了其他事务在T释放A上的锁之前不能再读取和修改A
源码如下:
@Override
public <T> T lock(Table table, Callable<T> callable) {
if (database.isPxcStrict()) {
return super.lock(table, callable);
}
return new MySQLNamedLockTemplate(jdbcTemplate,table.toString().hashCode()).execute(callable);
}
@Override
protected void doLock() throws SQLException {
jdbcTemplate.execute("SELECT * FROM " + this + " FOR UPDATE");
}
private boolean tryLock() throws SQLException {
return jdbcTemplate.queryForInt("SELECT GET_LOCK(?,10)", lockName) == 1;
}
1.3.3Flyway联接数据库
flyway使用JDBC联接数据库
private boolean hasUserVariableResetCapability() {
try {
jdbcTemplate.queryForStringList(userVariablesQuery);
return true;
} catch (SQLException e) {
LOG.debug("Disabled user variable reset as " + (database.isMariaDB() ? USER_VARIABLES_TABLE_MARIADB :USER_VARIABLES_TABLE_MYSQL)+ "cannot be queried (SQL State: " + e.getSQLState() + ",Error Code: " + e.getErrorCode() + ")");
return false;
}
}
1.3.4Flyway的启动速率
历时主要来源两个方面
(1).Flyway依次读取脚本中内容时的IO开支
(2).Flyway估算脚本checksum值的算法开支
对于IO开支而言,每位脚本倘若不是涉及大量的数据变更,只是表结构的变更,脚本的大小都十分小,可以不考虑。
二、Flyway的使用
接出来就步入题外话了,flyway该怎么使用呢?
以下是Java的使用方法。
2.1添加依赖
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>6.5.7</version>
</dependency>
2.2添加配置
java
spring:
flyway:
#是否启用
enabled: true
# 可以支持多个location, 用','隔开
locations: classpath:db/migration
#是否创建元数据表
validate-on-migrate: true
# flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉。这个默认值是
false 理论上作为默认配置是不科学的。
clean-disabled: true
# 如果数据库不是空表,需要设置成 true,否则启动报错
baseline-on-migrate: true
# 版本控制日志表,默认flyway_schema_history,不同系统建议修改数据
# table: flyway_schema_history
2.3创建sql文件
2.4启动项目即可三、Flyway解读3.1命令行
1.常用命令Migrate,Clean,Info,Validate,Baseline,Repair。
2.Migrate是指把数据库默认数据库迁移到最新版本。
3.Clean这个命令会去除指定库下所有的对象,包括table、view、triggers…,让数据库弄成空的状态。
用于复印所有Migrations的详尽和状态信息。
5.Validate是指验证早已应用的Migrations是否有变更,Flyway是默认是开启验证的。
6.Baseline针对早已存在表结构的数据库的一种解决方案,即实现在非空数据库中新建Metadata表,并把Migrations应用到该数据库。
7.Repair操作才能修补Metadata表,该操作在Metadata表出现错误时是十分有用的。
8.Repair会修补Metadata表的错误,一般有两种用途:
①移除失败的Migration记录,该问题只是针对不支持DDL事务的数据库。
②重新调整早已应用的Migratons的Checksums值,例如:某个Migratinon早已被应用,但本地进行了更改,又期望重新应用并调整Checksum值,不过尽量不要这样操作,否则可能导致其它环境失败。
3.2配置行
flyway配置解读
flyway.baseline-description对执行迁移时基准版本的描述.
flyway.baseline-on-migrate当迁移时发觉目标schema非空,并且带有没有元数据的表时,是否手动执
行基准迁移,默认false.
flyway.baseline-version开始执行基准迁移时对现有的schema的版本打标签,默认值为1.
flyway.check-location检测迁移脚本的位置是否存在,默认false.
flyway.clean-on-validation-error当发觉校准错误时是否手动调用clean,默认false.
flyway.enabled是否开启flywary,默认true.
flyway.encoding设置迁移时的编码,默认UTF-8.
flyway.ignore-failed-future-migration当读取元数据表时是否忽视错误的迁移,默认false.
flyway.init-sqls当初始化好联接时要执行的SQL.
flyway.locations迁移脚本的位置,默认db/migration.
flyway.out-of-order是否容许无序的迁移,默认false.
flyway.password目标数据库的密码.
flyway.placeholder-prefix设置每位placeholder的前缀,默认${.
flyway.placeholder-replacementplaceholders是否要被替换,默认true.
flyway.placeholder-suffix设置每位placeholder的后缀,默认}.
flyway.placeholders.[placeholdername]设置placeholder的value
flyway.schemas设定须要flywary迁移的schema,大小写敏感,默认为联接默认的schema.
flyway.sql-migration-prefix迁移文件的前缀,默认为V.
flyway.sql-migration-separator迁移脚本的文件名分隔符,默认__
flyway.sql-migration-suffix迁移脚本的后缀,默认为.sql
flyway.tableflyway使用的元数据表名,默认为schema_version
flyway.target迁移时使用的目标版本,默认为latestversion
flyway.url迁移时使用的JDBCURL,假如没有指定的话,将使用配置的主数据源
flyway.user迁移数据库的用户名
flyway.validate-on-migrate迁移时是否校准,默认为true.
3.3执行方法
Flyway的migration会在SpringBoot应用启动时手动执行,假若不想通过启动应用的方法执行,官方
提供了命令行、API、以及Maven和Gradle插件的形式,但总的来说就会麻烦一些,由于须要将早已
在SpringBoot中配置的参数,再到其他执行方法所各自要求的位置重新配置一遍,实用性通常。
3.4sql脚本命名规则
1.仅须要执行一次的,以小写“V”开头,V+版本后(版本号间的数字以“.”或者“_”分隔开,“_”会手动编译
成“.”)+"__"+文件描述+后缀名
2.须要执行多次的,以小写“R”开头,命名如R__clean.sqllinux查询数据库版本,R的脚本只要改变了才会执行,R不带版本号
3.V开头的比R开头的优先级要高。
前缀:用于版本控制(可配置)、撤消(可配置)和可重复迁移(可配置)VUR)
版本:带有点或下划线的版本可根据需要分隔任意数量的部分(不适用于可重复的迁移)
分隔符:(两个下划线)(可配置)__)
说明:下划线或空格分隔单词
后缀:(可配置.sql)
(可选)版本控制 SQL 迁移还可以省略分隔符和说明
四开发时注意事项
1.报错后须要删掉flyway_schema_history中记录,否则启动失败
2.V的优先级低于R,如果三个V迁移脚本和一个R(无论新建还是更改)一起执行,其中一个V报错,则V会
全部执行完成且记录到flyway_schema_history中,而R不执行且不记录,删掉表年报错记录后linux查询数据库版本,查询启
动,则执行原错误V和未执行的R
3.多个要执行的R中,假如出现了其中一个出现了错误,则在其后的R都不执行
4.R的执行次序依照命名来进行排序
5.一个文件中ddl并不由一个事务管理,例如创建三个表,中间创建表句子报错,则第一个表还是会创建
成功而且递交事务
6.早已执行过的迁移文件(V)不能更改,否则报错。
7.同一个迁移文件下同表内DDL未能回滚,DML可回滚,从报错点开始不往下执行,Flyway使用数据库锁
机制
8.版本号相同会报错(Foundmorethanonemigrationwithversion1.0.0.9)
9.同一个迁移文件下假定都是dml,这么假如中间出现错误,所有的dml句子就会回滚
10.删掉sql文件后启动会报错,报错如下:
If you removed this migration intentionally, run repair to mark the migration as
deleted.
五、部署上线时注意事项倘若不自动创建元数据表,则须要进行以下配置,用于手动创建
validate-on-migrate:true
Ifyouremovedthismigrationintentionally,runrepairtomarkthemigrationas
deleted.假如数据库不是空表,则需进行以下配置,否则启动报错
baseline-on-migrate:trueclean命令会删掉数据库中所有表,包括数据,结构等,这是不合理的,所以须要进行以下配置
clean-disabled:true(该配置因为默认值不合理,所以在V9版本中更改默认值由false为true)使用flyway要注意版本兼容问题,springboot与flyway,flyway与数据库版本,否则启动报错假如启动的时侯像忽视个别迁移文件,可进行以下参数配置
baseline-version=20210809,以忽视20210809版本以及之前的所有migration多人开发中,假如一个人递交V2一个人递交V1,而V2先入库执行了,这么V1入库就不会执行,如
果须要执行则需进行如下配置,并且不建议如此做
out-of-order=true六、支持的数据库版本
目前支持mysql5.7的社区版为7.15.0,支持mysql8.0的版本是8.2.0,8.2.1移不仅mysql支持,如文档原
文:
Extract MySQL code to plugin. This will need to be added as a new dependency.
flyway的8.2.1版本移除mysql的解决方案linux论坛,降低依赖:
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
七、总结
Flyway的引用确实便捷了后续我们团队的数据库版本管理,但各个团队使用场景皆有不同,所以本文只供想要学习Flyway的同学借鉴,另:flyway的社区版同专业版相比也是有一些区别的,类似下边的两个方面,所以在选择Flyway时需考虑引入对整体构架的提高,本文分享到这儿结束,谢谢你们耐心观看。
①社区版目前不支持版本回退
②社区版本没有任务队列和异步任务的支持,所以在大量变更时略有风险,尽量分拆