Flyway学习笔记

Flyway做为database migration开源工具,功能上像是git、svn这种代码版本控制。google搜索database migration,或者针对性更强些搜索database migration java,会有其它的framework、tool、甚至aws的service。因为项目使用到了flyway,而且确实google中排第一位的搜索结果就是flyway,那就之后有机会再与其它方案做比较,先对flyway做下学习笔记。

0.支持的数据库

支持数据库有 Oracle, SQL Server, SQL Azure, DB2, DB2 z/OS, MySQL (including Amazon RDS), MariaDB, Google Cloud SQL, PostgreSQL (including Amazon RDS and Heroku), Redshift, Vertica, H2, Hsql, Derby, SQLite, SAP HANA, solidDB, Sybase ASE and Phoenix。

1. 安装

1.1 Cli

从官网下载压缩包:https://flywaydb.org/documentation/commandline/

解压后cd到目录下,就可以直接执行flyway。解压后的文件夹结构如下图:

如果操作数据库,需要先在/conf/flyway.conf文件中做下配置,主要是对flyway.url、flyway.user和flyway.password(如何支持针对多个database,尚未做实验,待论),注释中给出了url的详细格式,可以根据环境自行添加。

1.2 Spring Integrating

dataSource中已经配置了数据库的driver、与flyway.conf中flyway.url格式相同的数据库信息,同时还有username和password,相当于这里就是为flyway配置conf文件

2 <bean id="flyway" class="org.Flyway.core.Flyway" init-method="migrate" depends-on="dataSource">
3     <property name="dataSource" ref="dataSource" />
4     <property name="locations" value="postgresql/db/migrations/" />
5 </bean>

每次app启动的时候,确切说在flyway的bean初始化的时候,就会自动检测扫描locations路径下的文件。locations文件夹中的文件,按照flyway官方默认的命名方式,就是用Vx_x__description.sql。sql文件,还有实现JdbcMigration接口生成的class文件(后文描述),都会列在schema_version表中,作为版本控制的原子项。比如在部署环境,只要war包中locations中的sql文件改变了,那么数据库就会做出相应的调整。

2. 配置

2.1 flyway.conf

flyway.conf:加载配置文件遵循下列顺序,并且后面加载的配置会覆盖前面的配置。

· <install-dir>/conf/flyway.conf

· <user-home>/flyway.conf

· <current-dir>/flyway.conf

文件中除了配置数据库信息,还能对比如prefix、separator、suffix做定义,默认prefix是V(执行一遍,并且版本号唯一,如果有重复就会报错)或R(重复执行,不需要版本号),separator是双下划线__,suffix是.sql。

官方文档中给出了SQL migration执行过程中扫描文件的顺序,即classpath:db/migration或者file system: 自定义文件夹。或者在执行flyway migration的时候使用-X参数,就能看到执行流程,这个确实有助于理解flyway的workflow。

2.2 drivers

flyway使用JDBC连接数据库,在drivers文件夹下有默认的几种,

· SQL Server (jTDS)

· MySQL

· MariaDB

· PostgreSQL

· Redshift

· H2

· Hsql

· Derby

· SQLite

如果要操作其它数据库,需要手动添加JDBC的driver到此文件夹下。

如果是用Spring集成,那么需要特别指定用的drivers是哪一个,比如org.postgresql.Driver

3. 基本指令

一共就6个基本指令:migrate、clean、info、validate、baseline、repair。强烈推荐在使用初期使用-X参数,log会显示flyway自己的业务逻辑。

4. 处理逻辑

4.1 schema_version

Flyway会生成一个表schema_version来记录文件的执行情况,关于生成与修改这个表的相关文件,在lib文件夹中有一个jar包flyway-core-2.1.1.jar,可以用WinZip打开,在下图位置示例了生成表的createMetaDataTable.sql文件,以及操作相关的class文件。

schema_version表中记录的每个脚本文件的执行情况,官方文档上有pending、success、failed、outdated和future,我还没有出现failed和outdated,不过有ignored,可能是因为用了V0。

4.2 文件处理逻辑

做为测试,我使用的执行步骤如下:

1. V1__create放入文件夹,migrate成功

2. V0__drop放入文件夹,migrate,结果是ignored

3. V0改为V1,numeric冲突,报错了

4. V0__drop改为V1_1__drop,migrate,执行成功

5. V1_1_drop删除,migrate,在schema_version表中,V1_1_drop状态为future,说明表中不会自己删除那些文件已不存在的item,而且drop掉的表不会再被创建,因为在schema_version表中V1__create的状态已经是success了。

5. FAQ

其中几个为官方文档的翻译,里面有些问题虽然没碰到,不过先自己翻译一遍加深理解。

原文链接:https://flywaydb.org/documentation/faq

对于降级操作(downgrade scripts/downward migrations)的支持

Flyway does NOT support downgrade scripts.

While the idea of downgrade scripts (popularized by Rails Migrations) is a nice one in theory, unfortunately it breaks down in practice. As soon as you have destructive changes (drop, delete, truncate, ...), you start getting into trouble. And even if you don‘t, you end up creating home-made alternatives for restoring backups, which need to be properly tested as well.

Flyway不支持降级的脚本:

一旦执行了诸如drop、delete、truncate这样的清除性动作,从之前的实验操作结果,我理解并不是说flyway不会甚至不能执行降级操作,毕竟drop、delete、truncate只是一些指令,flyway本身并没有能力看出来是哪些操作,这个回答应该是想说,最好不要做诸如此类的清除性动作,否则麻烦就来了,除非之前已经做了充分的备份以恢复数据。

Downgrade scripts assume the whole migration failed.

A migration can fail at any point. If you have 10 statements, it is possible for the 1st, the 5th, the 7th or the 10th to fail. There is simply no way to know in advance. Downgrade scripts are written to roll back an entire migration. This renders them effectively useless, even for non-destructive changes.

Migration执行失败可能发生在任何一个脚本,而降级操作相当于是在之前已经完成的基础上,那么如果前面的脚本执行失败,那么后面的操作就不会起作用,即便不是消除性操作。

我理解答案是想说明migration执行成功与否具有不确定性,而且版本号越高不确定性越强,因为会依赖先前的执行结果。

Maintain backwards compatibility between the DB and all versions of the code currently deployed in production.

This way a failed migration is not a disaster. The old version of the application is still compatible with the DB, so you can simply roll back the application code, investigate, and take corrective measures.

要确保数据库与线上各个版本代码的兼容性,才不会因为一次失败的migration脚本而造成重大损失。而且当真正执行失败的时候,也可以恢复回老版本的代码,再对错误做出修正。

A much better solution is a proper, well tested, backup and restore strategy.

It is independent of the database structure, and once it is tested and proven to work, no migration script can break it. For optimal performance, and if your infrastructure supports this, we recommend using the snapshot technology of your underlying storage solution. Especially for larger data volumes, this can be several orders of magnitude faster than traditional backups and restores!

这里是推荐在条件允许的情况下,用快照对已上线的系统做数据备份,说是比传统的数据备份与恢复要快。

如何做好热修复?

比如说现在已经上线的是版本7,正在开发的是版本8,而且版本8在DB schema上有些改动。此时有些bug导致需要对版本7做些热修复,也涉及到了schema的改动。

一般来说,虽然代码有多个分支,不过schema不会。所以可以将热修复的脚本标号为7.1,并且适用于修复版本7,和新的版本8。这样在版本8真正上线的时候,也会按照7、7.1、8的顺序执行脚本。

如果上述方案不行,还可以用outOfOrder(在flyway.conf有这个参数)属性,这样就可以允许不全部按照从小到大的顺序执行migration,也就是比schema_version中记录的最大值小的脚本,也能够被执行。

多个节点能够并行执行migration吗?

当然可以!Flyway使用数据库锁机制(locking technology of your database)来协调多个节点,从而保证多套应用程序可同时执行migration,而且集群控制也可做配置。

如果migration执行失败,会有回滚吗?

Flyway在不同的事物中执行migration,如果失败,那么事物就会回滚。不过不幸的是,现在只有DB2、PostgreSQL、Derby还有个别SQL Server扩展支持事物内的DDL。Other databases such as Oracle will implicitly sneak in a commit before and after each DDL statement, drastically reducing the effectiveness of this roll back. (没看太懂得一句)。一个可行的办法就是一个migration只包含单个DDL,只不过这样做比较累。

Flyway是否支持多schema?

当然支持!以下有几种策略来处理多schema的情况:

如果有多个相异的schema,可以用flyway的loop并且设置与schema对应的flyway.schemas。

如果schema的生命周期相同,那么可以只用一个flyway实例,设置flyway.schemas值为所有schemas以逗号隔开的字符串。所有的schema将只用到一个schema_version来记录脚本执行情况。(不知道此时schema_version表中会不会有专门的一列显示schema的名称)

如果schemas的生命周期不同,那就要启动多个flyway实例,每个实例处理自己的schema和metedata table,注意要把脚本分开放。

时间: 2024-08-29 20:01:39

Flyway学习笔记的相关文章

vector 学习笔记

vector 使用练习: /**************************************** * File Name: vector.cpp * Author: sky0917 * Created Time: 2014年04月27日 11:07:33 ****************************************/ #include <iostream> #include <vector> using namespace std; int main

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu

jQuery学习笔记(一):入门

jQuery学习笔记(一):入门 一.JQuery是什么 JQuery是什么?始终是萦绕在我心中的一个问题: 借鉴网上同学们的总结,可以从以下几个方面观察. 不使用JQuery时获取DOM文本的操作如下: 1 document.getElementById('info').value = 'Hello World!'; 使用JQuery时获取DOM文本操作如下: 1 $('#info').val('Hello World!'); 嗯,可以看出,使用JQuery的优势之一是可以使代码更加简练,使开

[原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓存,时间戳缓存

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Activiti 学习笔记记录(三)

上一篇:Activiti 学习笔记记录(二) 导读:上一篇学习了bpmn 画图的常用图形标记.那如何用它们组成一个可用文件呢? 我们知道 bpmn 其实是一个xml 文件

HTML&CSS基础学习笔记8-预格式文本

<pre>标签的主要作用是预格式化文本.被包围在 pre 标签中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. <pre>标签的一个常见应用就是用来表示计算机的源代码.当然你也可以在你需要在网页中预显示格式时使用它. 会使你的文本换行的标签(例如<h>.<p>)绝不能包含在 <pre> 所定义的块里.尽管有些浏览器会把段落结束标签解释为简单地换行,但是这种行为在所有浏览器上并不都是一样的. 更多学习内容,就在码芽网http://www.

java/android 设计模式学习笔记(14)---外观模式

这篇博客来介绍外观模式(Facade Pattern),外观模式也称为门面模式,它在开发过程中运用频率非常高,尤其是第三方 SDK 基本很大概率都会使用外观模式.通过一个外观类使得整个子系统只有一个统一的高层的接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节.当然,在我们的开发过程中,外观模式也是我们封装 API 的常用手段,例如网络模块.ImageLoader 模块等.其实我们在开发过程中可能已经使用过很多次外观模式,只是没有从理论层面去了解它. 转载请注明出处:http://bl

[原创]java WEB学习笔记48:其他的Servlet 监听器:域对象中属性的变更的事件监听器 (3 个),感知 Session 绑定的事件监听器(2个)

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程.一个复杂的对象有大量的组成部分,比如汽车它有车轮.方向盘.发动机.以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过