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
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
其中几个为官方文档的翻译,里面有些问题虽然没碰到,不过先自己翻译一遍加深理解。
对于降级操作(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,注意要把脚本分开放。
Flyway学习笔记的更多相关文章
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...
随机推荐
- P4249 [WC2007]剪刀石头布
有一个竞赛图,要给一些边定向,求三元环最多的数量 反过来考虑最少的不是环的三个点(称为不好的环),一定有一个点有2条入边,一个点有2条出边,一个点1入边1出边 可以对每一个不好的环只记录入边为2的点, ...
- JavaScript快速入门-BOM对象
一.什么是BOM 概念 BOM(Browser Object Model)即浏览器对象模型.BOM提供了独立于内容,而与浏览器窗口进行交互的对象: 核心 由于BOM主要用于管理窗口 ...
- bootstrap框架中data-toggle="tab"属性会取消a标签默认行为
这几天做公司项目用了bootstrap框架,在用导航组件的过程中,我发现在a标签里面添加data-toggle="tab"属性之后,这个a标签会失去默认行为,点击a标签的时候不会跳 ...
- GGTalk——C#开源即时通讯系统源码介绍系列(一)
坦白讲,我们公司其实没啥技术实力,之所以还能不断接到各种项目,全凭我们老板神通广大!要知道他每次的饭局上可都是些什么人物! 但是项目接下一大把,就凭咱哥儿几个的水平,想要独立自主.保质保量保期地一个个 ...
- 关于big-endian和little-endian
详解大端模式和小端模式 一.大端模式和小端模式的起源 关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的<格利佛游记>:Lilliput和Blefuscu这两个 ...
- python应用:生成简单二维码
概述 \(\quad\)第一篇python的应用就打算写一写用python生成简单的二维码啦.因为二维码在日常生活中越来越常用了,部分博客也用二维码来用作打赏的工具.但是要提醒大家的是,千万不要乱扫街 ...
- 《SLAM十四讲》个人学习知识点梳理
0.引言 从六月末到八月初大概一个月时间一直在啃SLAM十四讲[1]这本书,这本书把SLAM中涉及的基本知识点都涵盖了,所以在这里做一个复习,对这本书自己学到的东西做一个梳理. 书本地址:http:/ ...
- python类与对象各个算数运算魔法方法总结
1.python类与对象各个算术运算魔法方法总结: 2.各个魔法方法应用举例: 3.实例训练: (1)我们都知道在 Python 中,两个字符串相加会自动拼接字符串,但遗憾的是两个字符串相减却抛出异常 ...
- Kickstart Round H 2018
打了ks好久都没有更新 诶,自己的粗心真的是没救了,A题大数据都能错 A #include <iostream> #include <cstdio> #include < ...
- keyup在移动端失效解决方法
keyup在移动端失效解决方法: $("#OBJ").on("input propertychange", function(){ }); 采用 input 与 ...