一. 引言来
在软件我的项目开发工程中,一般来说我的项目都是几个开发人员齐头并进的,经常遇到的事件是,大家都同时提交数据库表批改语句后,并不告知其它人,或者几个开发人员同时批改一个表构造,导致其他人运行我的项目出错。
还有在我的项目上线运行过程中,经常会因为治理数据库表构造或者表数据版本而发愁,甚至有的时候还不得不为生产数据做迁徙操作。
以上的问题,咱们个别的操作都是约定 + 脚本,但效率不高,并且经常会因为版本抵触,不得不手动 merge
。这个时候一个麻利工具,用于数据库的移植的Flyway
利用而生,它的次要用于在你的利用版本一直降级的同时,降级你的数据库构造和外面的数据。
二、介绍来
1. Flyway 的特色
Flyway 大受欢迎是因为它具备如下劣势:
- 简略 很是容易装置和学习,同时迁徙的形式也很容易被开发者承受。
- 专一 专一于用作数据库迁徙、版本控制而并无其它副作用。
- 弱小 专为间断交付而设计,让 Flyway 在应用程序启动时迁徙数据库。
2. Flyway 的工作机制
Flyway 须要在 DB
中先建设一个 metadata
表 (缺省表名为 flyway_schema_history
), 在该表中保留着每次 migration
(迁徙)的记录, 记录蕴含 migration
脚本的版本号和 SQL 脚本的 checksum
值。下图示意了多个数据库版本。
对应的 metadata
表记录:spring
installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | Initial Setup | SQL | V1__Initial_Setup.sql | 1996767037 | axel | 2016-02-04 22:23:00.0 | 546 | true |
2 | 2 | First Changes | SQL | V2__First_Changes.sql | 1279644856 | axel | 2016-02-06 09:18:00.0 | 127 | true |
Flyway 扫描文件系统或应用程序的类门路读取 DDL 和 DML 以进行迁徙。依据metadata
表进行查看迁徙。** 若是脚本申明的版本号小于或等于标记为以后版本的版本号之一,将疏忽它们。其余迁徙是待处理迁徙:可用,但未利用。最初按版本号对它们进行排序并按程序执行 并将执行后果写入 metadata 表。
对应的 metadata
表记录:数据库
installed_rank | version | description | type | script | checksum | installed_by | installed_on | execution_time | success |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | Initial Setup | SQL | V1__Initial_Setup.sql | 1996767037 | axel | 2016-02-04 22:23:00.0 | 546 | true |
2 | 2 | First Changes | SQL | V2__First_Changes.sql | 1279644856 | axel | 2016-02-06 09:18:00.0 | 127 | true |
3 | 2.1 | Refactoring | JDBC | V2_1__Refactoring | axel | 2016-02-10 | 17:45:05.4 | 251 | true |
Flyway 反对命令行(须要下载命令行工具)和 Java Api,也反对构建工具 Maven 和 Gradle。这里咱们将眼光放在 Java Api 上。
3. Flyway 的规定
Flyway 是如何比拟两个 SQL 文件的前后程序呢?它采纳 采纳左对齐准则, 缺位用 0 代替。
1.0.1.1 比 1.0.1 版本高
1.0.10 比 1.0.9.4 版本高
1.0.10 和 1.0.010 版本号同样高, 每一个版本号局部的前导 0 会被疏忽
Flyway 将 SQL 文件分为 Versioned、Repeatable 和 Undo 三种:
- Versioned 用于版本升级, 每一个版本有惟一的版本号并只能执行一次。
- Repeatable 可反复执行, 当 Flyway检测到 Repeatable 类型的 SQL 脚本的
checksum
有变更, Flyway 就会从新利用该脚本. 它并不用于版本更新, 这类的migration
老是在 Versioned 执行当前才被执行。 - Undo 用于撤销具备雷同版本的版本化迁徙带来的影响。可是该回滚过于粗犷,过于机械化,通常不举荐应用。通常倡议应用 Versioned 模式来解决。
这三种的命名规定以下图:
- Prefix 可配置,前缀标识,默认值
V
示意 Versioned,R
示意 Repeatable,U
示意 Undo - Version 标识版本号, 由一个或多个数字形成, 数字之间的分隔符可用点
.
或下划线_
- Separator 可配置, 用于分隔版本标识与形容信息, 默认为两个下划线
__
- Description 形容信息, 文字之间可能用下划线
_
或空格 “ 分隔 - Suffix 可配置, 后续标识, 默认为
.sql
4.flyway 命令行
flyway 提供命令行工具, 罕用的命令包含:
- Clean: 删除所有创立的数据库对象, 包含用户、表、视图等. 留神不要在生产库上执行 clean 操作.
- Migrate: 对数据库顺次利用版本更改.
- Info: 获取目前数据库的状态. 那些迁徙曾经实现, 那些迁徙待实现. 所有迁徙的执行工夫以及后果.
- Validate: 验证已 Apply 的脚本是否有变更, Flyway 的 Migration 默认先做 Validate.
- Baseline: 依据现有的数据库构造生成一个基准迁徙脚本.
- Repair: 修复命令尽量不要应用, 修复场景有: 1. 移除失败的 migration 记录. 2. 曾经利用的 SQL 脚本被批改, 咱们想从新利用该 SQL 脚本.
maven 插件
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<configuration>
<user>${flyway.user}</user>
<password>${flyway.password}}</password>
<url>${flyway.url}</url>
</configuration>
</plugin>
5.flyway 最佳实际
1.SQL 的文件名
开发环境和生产环境的 migration SQL 不共用. 开发过程往往是多人合作开发, DB migration 也绝对比拟频繁, 所以 SQL 脚本会很多. 而生产环境 DB migration 往往由 DBA 实现, 每次降级通常须要提交一个 SQL 脚本.
DDL DML 离开
-
开发环境 SQL 文件倡议采纳工夫戳作为版本号, 多人一起开发不会导致版本号争用, 同时再加上生产环境的版本号, 这样的话, 未来手工 merge 成生产环境 V1.2d migration 脚本也比拟不便, SQL 文件示例:
- V20180317.14.59__V1.2_Add_SomeTables.sql
- V20180317.14.59__V1.0.1_ProjectName_{Feature|fix}_Developer_Description.sql
- 生产环境 SQL 文件, 应该是手动 merge 开发环境的 SQL 脚本, 版本号依照失常的版本, 比方 V2.1.5_001__Unique_User_Names.sql
2. migration 后的 SQL 脚本不应该再被批改.
3. spring.flyway.outOfOrder 取值 true /false
对于开发环境, 可能是多人合作开发, 很可能先 apply 了本人本地的最新 SQL 代码, 而后发现其余共事新近时候提交的 SQL 代码还没有 apply, 所以 开发环境应该设置 spring.flyway.outOfOrder=true, 这样 flyway 将能加载漏掉的老版本 SQL 文件; 而生产环境应该设置 spring.flyway.outOfOrder=false
4. 多个零碎专用要 DB schema
很多时候多个零碎专用一个 DB schema , 这时候应用 spring.flyway.table 为不同的零碎设置不同的 metadata 表, 缺省为 flyway_schema_history
5. 尽量配置.sql 到 filesystem,而不是我的项目工程下, 起因是不便替换,并不占用 jar 包大小
6. 不举荐应用 Undo,太过粗犷
7. 理论工程配置和目录
# flyway 配置内容,对应 FlywayAutoConfiguration.FlywayConfiguration 配置项
flyway:
enabled: true # 开启 Flyway 性能
cleanDisabled: true # 禁用 Flyway 所有的 drop 相干的逻辑,避免出现跑路的状况。locations: # 迁徙脚本目录
- classpath:db/migration/dev # 配置 SQL-based 的 SQL 脚本在该目录下
check-location: false # 是否校验迁徙脚本目录下。如果配置为 true,代表须要校验。此时,如果目录下没有迁徙脚本,会抛出 IllegalStateException 异样
url: jdbc:mysql://192.168.8.94:3399/flyway-test?useSSL=false&useUnicode=true&characterEncoding=UTF-8 # 数据库地址
user: root # 数据库账号
password: 1234123 #数据库明码
baseline-version: 1.0
baseline-description: "baseline"
encoding: UTF-8
out-of-order: true # 是否答应不按程序迁徙 开发倡议 true 生产倡议 false
# 如果指定 schema 蕴含了其余表, 但没有 flyway schema history 表的话, 在执行 flyway migrate 命令之前, 必须先执行 flyway baseline 命令.
# 设置 spring.flyway.baseline-on-migrate 为 true 后, flyway 将在须要 baseline 的时候, 主动执行一次 baseline.
baselineOnMigrate: true
table: flyway_schema_history
我的项目工程目录
三、扩大来
除开 Flyway
, 还有其它的数据库迁徙和版本控制工具,例如弱小的Liquibase
。两者具体的差别,在后续的文章论述。在以往的教训中,小我的项目,整体变动不大的用Flyway
,而大利用和企业应用用Liquibase
更适合。