Flyway 是一个开源的数据库迁移工具。相对于配置,它更倾向于简单和约定。它基于 7 个基本的命令:
Migrate
Clean
Info
Validate
Undo
Baseline
Repair
迁移可以使用 SQL(支持特定于数据库的语法,如PL/SQL、T-SQL) 或 Java(用于高级数据转换或处理 lob)编写。
它有命令行客户端,如果你在 JVM 上使用它,可以使用 Java API(也可以工作于 Android)应用于工程启动的时候迁移数据库。另外,你也可以使用 Maven 插件或者 Gradle 插件。
如果这还不够的话,还有一些插件可以用于 Spring Boot,Dropwizard, Grails, Play,SBT, Ant, Griffon,Grunt, Ninja 等等!
支持的数据库有:
- Oracle
- SQL Server(包括 Amazone RDS 和 Azure SQL 数据库)
- Azure Synapse
- DB2
- MySQL(包括 Amazon RDS 和 Azure 数据库 和 Google Cloud SQL)
- Aurora MySQL
- Percona XtraDB Cluster
- TestContainers
- PostgreSQL
- Aurora PostgreSQL
- Redshift
- CockroachDB
- SAP HANA
- Sybase ASE
- Informix
- H2
- HSQLDB
- Derby
- Snowflake
- SQLite
- Firebird
为什么要使用数据迁移?
首先,让我们从头开始,假设我们有一个叫做 Shiny 的项目,它的主要交付品是一个叫做 Shiny Soft 的软件,它连接到一个叫 Shiny DB 的数据库。如下图:
我们有自己的软件和数据库。太好了,这很可能就是你所需要的。
但在大多数项目中,这种简单的观点很快就会转化为:
我们现在不仅仅要从我们的环境中备份一次,而是多次,这带来了许多挑战。
我们已经很擅长在代码方面解决它们了
- 版本控制现在是通用的,每天都有更好的工具。
- 我们有可复制的构建和持续集成。
- 我们已经很好地定义了发布和部署过程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nlyAxm6v-1602764850309)(https://flywaydb.org/assets/balsamiq/SoftGreen.png)]
关于数据库应该怎么做?
不幸的是,我们在这方面做得不是很好。许多项目仍然依赖于手动应用 SQL 脚本。有时甚至不是这样(这里或那里的快速 SQL 语句来解决问题)。很快就出现了许多问题:
- 这台机器上的数据库处于什么状态?
- 这个脚本是否已经被应用?
- 生产中的快速修正是否已经应用到测试中?
- 如何设置一个新的数据库实例?
上述问题的答案,往往是:不知道!!!
数据库迁移是重新控制这种混乱局面的好方法
它们让你:
- 从头重新创建数据库
- 在任何时候都要明确数据库处于什么状态
- 以确定的方式从数据库的当前版本迁移到较新的版本
Flyway 是如何工作的?
最简单的场景就是将 Flyway 指向一个空的数据库。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VfIq9fdA-1602764850316)(https://flywaydb.org/assets/balsamiq/EmptyDb.png)]
它将尝试定位它的实例历史表。由于数据库是空的,Flyway 将不会找到历史,而是创建。
你现在有一个数据库,默认情况下只有一个空表 flyway_schema_history:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aGVU6IYw-1602764850317)(https://flywaydb.org/assets/balsamiq/EmptySchemaVersion.png)]
此表将用于跟踪数据库的状态。
紧接着,Flyway 将开始扫描应用程序的文件系统或类路径以进行迁移。它们可以使用 SQL 或者 Java 编写。
然后根据版本号对迁移进行排序,并按顺序应用:
随着每次迁移的应用,数据库实例历史表会相应地更新:
flyway_schema_history
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 将再次扫描应用程序的文件系统或类路径以进行迁移。迁移将根据数据库实例历史表进行检查。如果它们的版本号小于或等于标记为当前版本的版本号,则忽略它们。
其余迁移是暂挂迁移:可用,但未应用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cl0G1o0S-1602764850320)(https://flywaydb.org/assets/balsamiq/PendingMigration.png)]
然后按版本号排序,按以下顺序执行:
相应更新模式历史表:
flyway_schema_history
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 !每当需要更新数据库时,无论是 DDL 还是 DML,只需创建一个版本号高于当前版本号的新迁移。下一次 Flyway 启动时,它会找到它并相应的升级数据库。