Flyway介绍
Flyway是⼀款开源的数据库版本管理⼯具,它更倾向于规约优于配置的⽅式。Flyway可以独⽴于应⽤实现管理并跟踪数据库变更,⽀持数据库版本⾃动升级,并且有⼀套默认的规约,不需要复杂的配置,Migrations可以写成SQL脚本,也可以写在Java代码中,不仅⽀持CommandLine和JavaAPI,还⽀持Build构建⼯具和SpringBoot等。
⽀持的数据库
⽀持数据库有Oracle,SQLServer,SQLAzure,DB2,DB2z/OS,MySQL(includingAmazonRDS),MariaDB,GoogleCloudSQL,PostgreSQL(includingAmazonRDSandHeroku),Redshift,Vertica,H2,Hsql,Derby,SQLite,SAPHANA,solidDB,SybaseASEandPhoenix
PS:不⽀持分布式数据库,譬如阿⾥云的DRDS
工作原理
场景⼀:使⽤flyway迁移到⼀个空数据库
flyway会新建⼀个元数据表(SCHEMA_VERSION)⽤于记录migrate信息和跟踪数据库的状态。
然后,扫描指定路径下的脚本⽂件,按照版本号的顺序执⾏脚本。
最后,SCHEMA_VERSION表中会⽣成相关的记录。
场景⼆:使⽤flyway迁移到⼀个⾮空数据库
下图Migration1和Migration2为已执⾏过的脚本,Migration2.1为准备执⾏的脚本。
flyway会扫描SCHEMA_VERSION表,判断Migration1、Migration2、Migration2.1是否有执⾏成功的记录,如果有,则不会再执⾏,如果没有,则该脚本进⼊等待状态,最后flyway会按照版本顺序执⾏脚本SCHEMA_VERSION表中会⽣成相关的记录。
客户端使⽤
1.从官⽹下载安装包https://flywaydb.org/documentation/commandline/,并且解压
“flyway.conf”为flyway的配置⽂件,主要配置数据库信息和flyway规则信息;
“sql”⽂件夹⽤来存放数据库脚本⽂件;
“drivers”⽂件夹⽤来存放JDBC的driver;
2.数据库脚本的命名规则
例⼦:V20181114__itsp.sql
"V":默认prefix是V(执⾏⼀遍,并且版本号唯⼀,如果有重复就会报错)或R(重复执⾏,不需要版本号)
"20181114":版本号
"__":两个下划线
"itsp":描述
".sql":后缀名数据库脚本按照上⾯规则命名,flyway就可以识别并且执⾏脚本。
命名规则也可以在“flyway.conf”⽂件中配置。
3.flyway命令Flyway主要基于6种基本命令:Migrate,Clean,Info,Validate,Baselineand Repair
flyway migrate
此命令会⾃动检查数据库脚本是否有变化,如果有变化,则执⾏脚本,更新数据库版本,如果数据库初始状态是空库,则会⾃动创建schema_version表,⽤于存储数据库操作的版本记录,只要数据库脚本有变化,都需要执⾏此命令。
flyway clean
清除schema_version中记录所有表结构,视图,存储过程,函数以及所有的数据等都会被清除。
flyway info
打印schema_version中记录信息。
flyway validate
Validate是指验证已经Apply的Migrations是否有变更,Flyway是默认是开启验证的。
flyway baseline
Baseline是指数据库⾮空状态下使⽤flyway⾸先执⾏的命令,⽤于创建schema_vision表。
flyway repair
Repair会修复Metadata表的错误,通常有两种⽤途:a)移除失败的Migration记录,该问题只是针对不⽀持DDL事务的数据库。b)重新调整已经应⽤的Migratons的Checksums值,⽐如:某个Migratinon已经被应⽤,但本地进⾏了修改,⼜期望重新应⽤并调整Checksum值,不过尽量不要这样操作,否则可能造成其它环境失败。
4.命令执⾏
运⾏CMD,进⼊flyway客户端的⽬录中执⾏:flywaymigrate
执⾏完毕后,数据库按照脚本新建了三个业务表和⼀张flyway的元数据表。
元数据表中的数据就是记录三个脚本的运⾏情况。
SpringBoot整合Flyway
1.引⼊maven依赖
2.配置⽂件
配置详解:
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-sufix设置每个placeholder的后缀,默认}.
flyway.placeholders.[placeholdername]设置placeholder的valueflyway.schemas设定需要flywary迁移的schema,⼤⼩写敏感,默认为连接默认的schema.
flyway.sql-migration-prefix迁移⽂件的前缀,默认为V.
flyway.sql-migration-separator迁移脚本的⽂件名分隔符,默认__
flyway.sql-migration-sufix迁移脚本的后缀,默认为.sql
flyway.tableflyway使⽤的元数据表名,默认为schema_version
flyway.target迁移时使⽤的⽬标版本,默认为latestversion
flyway.url迁移时使⽤的JDBCURL,如果没有指定的话,将使⽤配置的主数据源
flyway.user迁移数据库的⽤户名
flyway.validate-on-migrate迁移时是否校验,默认为true.
3.启动Springboot,flyway就会⾃动从脚本路径中按照规则执⾏脚本
4.遇到的问题
a)在遇到需要先加载数据⽅⾯的操作,都需要在flyway执⾏完毕后才能加载不然会出现找不到新增的表或者修改的表结构、新增表数据。
解决办法:在对应的bean上加上@DependsOn("flywayInitializer")注解。
b)在本地Run和Tests都会使⽤内存数据库,其中的spring.jpa.hibernate.ddl-auto都设置为validate,Schema不需要Hibernate⾃动⽣成,并期望使⽤Flyway,⽽在线上环境会使⽤真实数据库,并不期望使⽤Flyway,如何实现呢?
解决⽅案:可以在common.properties中配置flyway.enabled=false,然后在local或dev的配置中启⽤Flyway即可。通常推荐使⽤此模式,毕竟可以对不同的环境进⾏控制,另外本地Run不会依赖真实数据库,⼜能保证数据库Schema是按脚本创建的。
c)若项⽬有多个团队同时开发不同的功能,需要新建多个分⽀,并且都会涉及到数据库Schema更改,当后期Merge时,Migration的版本如何控制并且不会产⽣数据库更改的冲突呢?
解决⽅案:如果两个分⽀的数据库更改有冲突,要么最初数据库设计不合理,要么⽬前数据库更改不合理,所以需要团队进⾏全局考虑和协调。⽽针对数据库在同⼀段时间有修改,但不会造成冲突的情况,通常实际项⽬中主要存在这样的情况,那可以设置,这样允许当v1和v3已经被应⽤后,v2出现时同样也可以被应⽤。其实在本地使⽤内存数据库不会存在该问题,因为数据库所有对象会⾃动清除掉,⽽在local或dev中使⽤真实数据库时可遇到这样的问题,因此需要注意⼀下了。