六年前Flyway已经是我TDD开发、持续集成工具栈中的重要一环了,作为早期用户,我早就应该为它做个”广告“,可惜对创业者来说时间太宝贵了,现在趁着疫情才有机会在家里总结点东西。
虽然现在Flyway已经是Spring-Boot集成工具的一环,但是我发现还是少有人了解它的威力。
关系数据库之殇
你在使用关系数据库的过程中,是否曾经遇到以下情况,甚至因此一度想要放弃或已经放弃关系数据库?
场景一:开发环境,多人共用一套数据库
开发正调试着,忽然代码报错“XX字段不存在”:谁TMD又把表结构给改了……
场景二:开发环境,每个人各自搭建自己的数据库
开发完一个功能,提交代码、更新,重启准备调试下,代码报错“XX表不存在”
吼一嗓子:谁又改表结构了?什么?每个人都要把xxx.sql执行一遍?
……
新员工:我要搭一套开发数据库,到底应该执行哪些SQL脚本?
场景三:开发转测试
测试:你看这个功能是不是有个Bug?
开发1:哦,你要执行一下这个SQL脚本。
测试:嗯,现在没问题了,但是怎么保证这个脚本没有Bug,我能再重现、测试一遍吗?
开发:额~,你重新搭一遍数据库吧……
场景四:搭建一套演示环境
执行SQL脚本1、SQL脚本2、SQL脚本3……启动服务失败!
什么?这个脚本N是测试版本的,war包是已经上线的版本?
删库再来一遍……
场景五:放弃关系数据库的坑
受不了关系数据库了,我们切MongoDB吧……嗯,控制台果然清静了。
……
几个版本后:
生产环境某些数据查不到了、还有类型不匹配,神马?
A字段改过名,B字段换了个类型?
如果上面的问题,你一个都没遇到过,要么是你所做的项目太简单,要么你们的开发流程非常规范,或者变更控制得太好了,本文你大可跳过了。
如果你正被上面的问题困扰,你可能会因此想要入另一个坑:NoSQL,那么恭喜你将遇到更多的坑,比如关联查询问题、数据版本问题……
注:这里并不否定NoSQL的价值,各种NoSQL是关系数据库的良好补充。 但是如果想将NoSQL做为关系数据库的替代,那么你将会陷入比关系数据库还多的线上问题之中。
如果你看到这里,说明你不想逃避问题,那么让我们一起来认识这个关系数据库升级管理的利器——Flyway
Flyway原理介绍
Flyway是什么?一句话概括,Flyway就是一个数据库版本管理组件。它的原理非常简单:
- 项目启动时拉起Flyway,先检查数据库里面有没有Flyway元数据表,没有则创建;
- 检查Flyway元数据表中的记录,哪些脚本已经执行过,当前版本是什么;
- 查找代码中的(名称满足规则的)数据库升级脚本,找出版本号大于(Flyway元数据)当前版本的脚本,逐个执行并记录执行结果到Flyway元数据表。
你没看错,以上三点就是Flyway最核心的功能,对非JVM开发者我推荐在理解以上思想的基本上自己开发一套。
大道至简,最简单的设计往往是最有效的。通过以上功能,我们可以很容易做到:
- 代码与数据库建表&升级脚本放在一起同步管理,通过代码(SQL)就可以了解到表结构;
- 无须人工执行任何脚本,运行代码或服务即可完成(数据库表结构的)环境搭建;
- 从任一版本的环境(表结构),都可以通过运行指定(新)版本的代码或服务来自动升级到指定新版本;
- (配合内存数据库/Docker/清库脚本)数据库搭建&升级脚本很容易与代码一起反复测试。
总之,用上Flyway之后,关系数据库的”关系“,不再是限制你开发效率的瓶颈,反而成为开发&测试的必要约定,提升版本质量的重要保障。
快速上手
不管工具多强大,如何用起来,是我们首要关心的,让我们以各种Java项目环境,来看一下如何在代码中将Flyway用起来,再由各位自己去细品Flyway对关系数据库版本管理带来的巨大改变。
注:所有示例都基于Maven,用Gradle的自己翻译下依赖,二