为什么要用Flyway
在日常开发中,我们经常会遇到下面的问题:
-
自己写的SQL忘了在所有环境执行;
-
别人写的SQL我们不能确定是否都在所有环境执行过了;
-
有人修改了已经执行过的SQL,期望再次执行;
-
需要新增环境做数据迁移;
-
每次发版需要手动控制先发DB版本,再发布应用版本;
-
其它场景...
由于项目需求的变化,或者前期设计缺陷,导致在后期需要修改数据库,这应该是一个比较常见的事情,如果项目还没上线,你可能把表删除了重新创建,但是如果项目已经上线了,就不能这样简单粗暴了,每次运维部署项目,还得手动执行一遍SQL文件。我们需要通过 SQL 脚本在已有数据表的基础上进行升级。
有了flyway,这些问题都能得到很好的解决。
使用了 Flyway 之后,如果再想进行数据库版本升级,就不用该以前的数据库脚本了,直接创建新的数据库脚本,项目在启动时检测了有新的更高版本的脚本,就会自动执行,这样,在和其他同事配合工作时,也会方便很多。因为正常我们都是从 Git 上拉代码下来,不拉数据库脚本,这样要是有人更新了数据库,其他同事不一定能够收到最新的通知,使用了 Flyway 就可以有效避免这个问题了。
所有的脚本,一旦执行了,就会在 flyway_schema_history (java www.fhadmin.cn ) 表中有记录,如果你不小心搞错了,可以手动从 flyway_schema_history 表中删除记录,然后修改 SQL 脚本后再重新启动(生产环境不建议)。
Flyway是如何工作的
Flyway工作流程如下:
1、项目启动,应用程序完成数据库连接池的建立后,Flyway自动运行。
2、初次使用时,Flyway会创建一个flyway_schema_history
表,用于记录sql执行记录。
3、Flyway会扫描项目指定路径下(默认是classpath:db/migration
)的所有sql脚本,与flyway_schema_history
表脚本记录进行比对。如果数据库记录执行过的脚本记录,与项目中的sql脚本不一致,Flyway会报错并停止项目执行。
4、如果校验通过,则根据表中的sql记录最大版本号,忽略所有版本号不大于该版本的脚本。再按照版本号从小到大,逐个执行其余脚本。
项目中使用Flyway
首先,在pom文件中引入flyway的核心依赖包:
1、引入核心依赖包:
<dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> <version>5.2.4</version> </dependency>
这里使用5.2.4版本。经测试7.0.0版本与目前我们使用的springboot版本有冲突,会导致flyway不执行。因此我们尽量不要使用高版本的flyway。
2、配置文件:
简单配置一个属性即可使用
# java www.fhadmin.cn # flyway 配置 spring: flyway: # 启用或禁用 flyway enabled: true # flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉。这个默认值是 false 理论上作为默认配置是不科学的。 clean-disabled: true # SQL 脚本的目录,多个路径使用逗号分隔 默认值 classpath:db/migration locations: classpath:db/migration # metadata 版本控制信息表 默认 flyway_schema_history table: flyway_schema_history # 如果没有 flyway_schema_history 这个 metadata 表, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令 # 设置为 true 后 flyway 将在需要 baseline 的时候, 自动执行一次 baseline。 baseline-on-migrate: true # 指定 baseline 的版本号,默认值为 1, 低于该版本号的 SQL 文件, migrate 时会被忽略 baseline-version: 1 # 字符编码 默认 UTF-8 encoding: UTF-8 # 是否允许不按顺序迁移 开发建议 true 生产建议 false out-of-order: false # 需要 flyway 管控的 schema list,这里我们配置为flyway 缺省的话, 使用spring.datasource.url 配置的那个 schema, # 可以指定多个schema, 但仅会在第一个schema下建立 metadata 表, 也仅在第一个schema应用migration sql 脚本. # 但flyway Clean 命令会依次在这些schema下都执行一遍. 所以 确保生产 spring.flyway.clean-disabled 为 true schemas: flyway # 执行迁移时是否自动调用验证 当你的 版本不符合逻辑 比如 你先执行了 DML 而没有 对应的DDL 会抛出异常 validate-on-migrate: true
# 对执行迁移时基准版本的描述. flyway.baseline-description #当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移,默认false. flyway.baseline-on-migrate =false #开始执行基准迁移时对现有的schema的版本打标签,默认值为1. flyway.baseline-version=1 #检查迁移脚本的位置是否存在,默认false. flyway.check-location=false #当发现校验错误时是否自动调用clean,默认false. flyway.clean-on-validation-error=false #是否开启flywary,默认true. flyway.enabled=true #设置迁移时的编码,默认UTF-8. flyway.encoding #当读取元数据表时是否忽略错误的迁移,默认false. flyway.ignore-failed-future-migration #当初始化好连接时要执行的SQL. flyway.init-sqls #迁移脚本的位置,默认db/migration. flyway.locations #是否允许无序的迁移,默认false. flyway.out-of-order #目标数据库的密码. flyway.password #设置每个placeholder的前缀,默认${. flyway.placeholder-prefix #是否要被替换,默认true. flyway.placeholder-replacementplaceholders #设置每个placeholder的后缀,默认}. flyway.placeholder-suffix #设置placeholder的value flyway.placeholders.[placeholder name] #设定需要flywary迁移的schema,大小写敏感,默认为连接默认的schema. flyway.schemas #迁移文件的前缀,默认为V. flyway.sql-migration-prefix #迁移脚本的文件名分隔符,默认__ flyway.sql-migration-separator #迁移脚本的后缀,默认为.sql flyway.sql-migration-suffix #使用的元数据表名,默认为schema_version flyway.tableflyway #迁移时使用的目标版本,默认为latest version flyway.target #迁移时使用的JDBC URL,如果没有指定的话,将使用配置的主数据源 flyway.url #迁移数据库的用户名 flyway.user #迁移时是否校验,默认为true flyway.validate-on-migrate
# flyway 配置 spring: flyway: # 启用或禁用 flyway enabled: true # flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉。这个默认值是 false 理论上作为默认配置是不科学的。 clean-disabled: true # SQL 脚本的目录,多个路径使用逗号分隔 默认值 classpath:db/migration locations: classpath:db/migration # metadata 版本控制信息表 默认 flyway_schema_history table: flyway_schema_history # 如果没有 flyway_schema_history 这个 metadata 表, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令 # 设置为 true 后 flyway 将在需要 baseline 的时候, 自动执行一次 baseline。 baseline-on-migrate: true # 指定 baseline 的版本号,默认值为 1, 低于该版本号的 SQL 文件, migrate 时会被忽略 baseline-version: 1 # 字符编码 默认 UTF-8 encoding: UTF-8 # 是否允许不按顺序迁移 开发建议 true 生产建议 false out-of-order: false # 需要 flyway 管控的 schema list,这里我们配置为flyway 缺省的话, 使用spring.datasource.url 配置的那个 schema, # 可以指定多个schema, 但仅会在第一个schema下建立 metadata 表, 也仅在第一个schema应用migration sql 脚本. # 但flyway Clean 命令会依次在这些schema下都执行一遍. 所以 确保生产 spring.flyway.clean-disabled 为 true schemas: flyway # 执行迁移时是否自动调用验证 当你的 版本不符合逻辑 比如 你先执行了 DML 而没有 对应的DDL 会抛出异常 validate-on-migrate: true
3、创建db/migration
因为flyway默认是读取resources/db/migration下的文件夹,如果我们需要修改这个路径,可以在配置文件中实现
4、编写sql文件
此处的SQL语句命名需要遵从一定的规范,否则运行的时候flyway会报错。命名规则主要有两种:
-
仅需要被执行一次的SQL命名以大写的"V"开头,后面跟上"0~9"数字的组合,数字之间可以用“.”或者下划线"_"分割开,然后再以两个下划线 __ 分割,其后跟文件名称,最后以.sql结尾。比如,
V20210707__create_user.sql
、V20210707__add_user.sql
。 -
可重复运行的SQL,则以大写的“R”开头,后面再以两个下划线分割,其后跟文件名称,最后以.sql结尾。。比如,
R__truncate_user_dml.sql
。
其中,V开头的SQL执行优先级要比R开头的SQL优先级高。
V:固定大写
20210707.01:20210707是日期,后面用.01代表序号
因为flyway的执行是有个顺序的,比如你执行了V2021__create_user,又执行V2020_update_user。就会报错,原因就是2020<2021。所以我们要保证序号是依次增大。
Flyway 是如何比较两个 SQL 文件的先后顺序呢?它采用 采用左对齐原则, 缺位用 0 代替 。举几个例子:
1.0.1.1 比 1.0.1 版本高。 1.0.10 比 1.0.9.4 版本高。 1.0.10 和 1.0.010 版本号一样高, 每个版本号部分的前导 0 会被忽略。
__:这个是两个 _
create_user是一个简单的sql描述
.sql:以.sql结尾的文件后缀是约定
我们只要在数据库中创建flyway这个数据库,启动项目,flyway就会执行sql文件,创建user表,并且会自动生成一个flyway_schema_history表
从这段启动日志中,我们可以看到 Flyway 的执行信息,数据库脚本的执行执行,同时这里还说了,Flyway 还给创建了一个 flyway_schema_history 表,这个表用来记录数据库的更新历史。
flyway_schema_history里面会去记录sql文件的执行记录,每次启动项目,都会去flyway_schema_history看sql是否执行过,如果没有执行过,说明这个sql是新的sql,就会自动执行,并且记录到表里面。
有了这条记录,下次再启动项目,V20210707.01、V20210707.02、V20210708.01 这个三个脚本文件就不会执行了,因为系统知道这个脚本已经执行过了,如果你还想让这些脚本再执行一遍,需要手动删除 flyway_schema_history 表中的对应记录,那么项目启动时,这个脚本就会被执行了。
R开头的文件和V开头的文件略有不同,R开头的文件只要发送修改,都会执行一遍。V开头的文件如果执行过一般,在发送修改,就会报错。为了控制版本,我们尽量使用V开头的文件,这样我们也可以很清楚的看到每个版本中的sql文件。
常见问题
问题1
flyway遇到的问题Caused by: java.lang.ClassNotFoundException: org.flywaydb.core.api.callback.FlywayCallbac
原因:springboot版本和flyway版本不一致,一般是flyway版本过高。
解决办法:将flyway的版本降到5.2.4就ok了
问题2
springboot 整合flyway 但是不生效,flyway不会自动执行sql
原因:如上
原因2:项目中没有配置数据库,没有引入sq依赖或者配置
解决办法:如上
解决办法2:引入sql依赖,在yml文件中配置sql信息
问题3
flyway出错 FlywayException: Validate failed: Detected failed migration to version
原因:sql脚本和数据库中有冲突,需要检查sql脚本哪里错了。简单的说就是V开头的sql文件,已经执行过了,在 flyway_schema_history 表里面有这个数据,但是你又改动了sql文件,导致再次执行的时候报错。
解决办法:新建一个sql文件,不要修改原来以V开头的文件或者在flyway_schema_history表中找到文件相关执行记录,删掉重新执行。
相关推荐
2. **迁移脚本**:Flyway支持多种数据库方言,允许使用SQL脚本或者Java类进行数据库迁移。SQL脚本通常命名为`V<version>__<description>.sql`,其中`<version>`是版本号,`<description>`是对脚本的简短描述。Java类...
Flyway 可以独立于应用实现管理并跟踪数据库变更,支持数据库版本自动升级,并且有一套默认的规约,不需要复杂的配置,Migrations 可以写成 SQL 脚本,也可以写在 Java 代码中,不仅支持 Command Line 和 Java API,...
Flyway 可以独立于应用实现管理并跟踪数据库变更,支持数据库版本自动升级,并且有一套默认的规约,不需要复杂的配置,Migrations 可以写成 SQL 脚本,也可以写在 Java 代码中,不仅支持 Command Line 和 Java API,...
Flyway是一款强大的数据库版本管理工具,它以Java为基础,旨在帮助开发者和运维人员有效地管理和维护数据库的演变。在软件开发过程中,随着项目的发展,数据库结构也会随之改变,这些变化需要被系统地记录和管理,...
- Java-based migrations:除了SQL脚本,Flyway还支持用Java编写迁移,这在处理复杂逻辑时非常有用。 - Callbacks:在迁移前后执行自定义代码,用于额外的清理或验证任务。 - 命令行工具:提供方便的命令行接口,...
Flyway允许用户使用SQL脚本或Java代码编写迁移脚本(Migrations),不仅支持命令行(Command Line)和Java API接口,还能集成到各种构建工具(如Maven、Gradle)及框架(例如Spring Boot)中。这使得它能够在分布式...
Flyway可以独立于应用实现管理并跟踪数据库变更,支持数据库版本自动升级,并且有一套默认的规约,不需要复杂的配置。 Flyway支持的数据库 Flyway目前支持的数据库主要有:Oracle, SQL Server, SQL Azure, DB2, ...
Flyway是一款数据库版本控制管理工具,支持数据库版本自动升级,Migrations可以写成sql脚本,也可以写在java代码里。Flyway提供了多种方式来集成到项目中,如Command Line、Java API、Build构建工具和Spring boot。...
Flyway作为一个数据库版本管理工具,解决了开发团队在数据库同步上的痛点,通过版本化的SQL脚本管理和自动化迁移,确保每个开发者的数据库状态保持一致。同时,其丰富的功能、广泛的数据库支持以及与Maven和Spring的...
在项目的不同阶段,当数据库结构发生变化时,Flyway通过读取SQL脚本或者Java类进行数据库的版本升级。它确保了数据库状态与代码保持一致,简化了数据库的版本控制,尤其是在团队协作和持续集成环境中。 在这个...
Flayway是一款强大的数据库版本管理工具,它使得开发者能够通过SQL脚本或者Java类来管理数据库的迁移。在“flayway.rar”这个压缩包中,包含了一个名为“flyway-demo-master”的示例项目,该项目展示了如何在项目...
在实际操作中,开发者可能会使用像Flyway或Liquibase这样的数据库版本控制工具来管理这些脚本,自动化数据库的版本升级和回滚。 总的来说,"JavaWeb信息管理系统包含数据库脚本文件.zip"是一个包含系统核心数据结构...
2. **迁移脚本编写**:根据项目的数据库变更,编写SQL脚本,每个脚本代表一个数据库版本。 3. **启动服务**:当DropWizard服务启动时,Flyway会自动检测并执行未执行过的迁移脚本,从而更新数据库到最新版本。 4. **...
此外,开源工具如Flyway和Liquibase也是Java开发中常用的数据迁移工具,它们可以集成到构建流程中,自动化迁移过程。 在设计数据库迁移系统时,还需要考虑并发控制、错误处理和回滚策略,以确保在出现问题时能够...
2. 自动化:利用脚本或持续集成工具自动化比较过程,减少人工错误。 3. 文档记录:记录每次比较的结果和采取的行动,便于日后查阅和审计。 总之,数据库差异比较是数据库管理中不可或缺的一部分,通过有效的工具和...
2. **文件命名规则**:SQL脚本文件及Java代码类名必须遵循特定的命名规则:`V[_][__description]`。其中,版本号之间使用小数点`.`或下划线`_`分隔,版本号与描述之间则使用两个下划线`__`分隔。例如,一个有效的...
这些工具提供了自动化的方式来管理数据库版本,使得开发者可以编写SQL脚本或者Java类来描述数据库的变更,并在需要的时候安全地应用这些变更。 在"evodb-master"这个压缩包中,很可能是包含了一个使用了上述迁移...
1. **SQL脚本比对**:编写SQL脚本来导出每个数据库的表结构和数据,然后通过文本比对工具(如Beyond Compare)来查找差异。 2. **数据库比对工具**:有许多专业工具如Red Gate的SQL Compare、SQL Data Compare,...
在项目开发过程中,数据库结构往往需要随着需求的变更而变化,Flyway提供了一种结构化的管理方式,通过SQL脚本或Java类进行数据库版本升级。在pt-backend中,Flyway的集成确保了数据库的更新与代码同步,避免了手动...