不知道你有没有遇到过这种场景,一套代码部署在不同的环境中,随着时间的过去,各个环境代码有版本差异,代码层面可以通过不同的版本来控制,但是数据库层面经常容易忘记更新!

前言

比如刚开始环境 A 和环境 B 的代码版本是一样的,但是随着版本的迭代,环境 A 的系统一直持续迭代,但是环境 B 的系统由于种种原因没有升级,一直保持在最初的版本。如果某个时候需要对环境 B 的系统进行升级的话,你会发现,中间已经过了好多个版本,各个版本的差距很大,数据库结构有调整,不能直接打包发布,需要把之前所有对环境 A 调整的 SQL 都在环境 B 中执行一遍才行。

这个时候如果 SQL 版本做的好的问题不大,依次执行就行了,但是如果中间有人员离职或者记录缺失,那只能通过对比数据库结构来进行解决了。

数据迁移

前面我们的提到的场景专业的名词叫数据迁移,那为什么会出现数据迁移的场景呢?我从官网截了一张图大家可以看下,虽然说可能跟我实际开发不是一样,但是也差不多类似会出现这种场景,存在多个环境。可以看到虽然我们的代码可以通过版本迭代来控制,但是我们的数据库却不行,很多时候连脚本是否执行过都会忘记,这种事情光靠人记是很难的。

Flyway

Flyway 就是用来解决像这样的数据库迁移的工具,接入了 Flyway 过后,在数据库中会生成一张默认名为flyway_schema_history 的数据表,用来追踪数据库的变化。程序启动的时候 Flyway 都会在文件系统或者 classpath 路径下面寻找迁移脚本。每个迁移脚步都有相应的命名规则,Flyway 会根据文件的版本号进行迁移,每次迁移过后都会在flyway_schema_history 表中插入一条类似如下的记录,记录版本已经对应的脚本文件和校验码等信息:

每次启动的时候只会执行最高版本的脚本,而且如果版本没变,脚本变了是启动不了的。

Flyway 的迁移类型

版本迁移

最常见的迁移就是就是版本化迁移,每次迁移都会对应的迁移版本,迁移的版本必须全局唯一,版本迁移最大的特点就是依次只被执行依次。

撤销迁移

每个撤销迁移都对应的一个版本迁移,也就是说撤销迁移是针对版本迁移所存在的,每一个撤销迁移与版本迁移都是一一对应的,而且对应的版本号必须一致。

可重复迁移

可重复迁移有描述和校验码,但是没有版本号,程序在每次启动的时候,如果发现脚本文件有变化就会执行。

基于 SQL 的迁移

上面提到的几种类型都是基于 SQL 文件来执行的,只不过每种类型的命名格式不一样,下图是从官网上截下来的,大家看下每种类型的文件应该按照如下的格式去命令,其中的 Separator 是两个下划线。

主要分为下面几个部分:

prefix:前缀,不同的类型采用不同的前缀,版本迁移使用 V,撤销迁移使用 U,可重复迁移使用 R,当然这些都是可配置的;

Version:版本号,可以使用点符号或者单下划线链接;

Separator:分隔符,两个下划线,也是可以配置的;

Description:版本描述可以用下划线和空格分隔;

Suffix:后缀,一般都是 .sql

SpringBoot 项目接入 Flyway

SpringBoot 项目接入 Flyway 非常简单,主要分为如下几步即可,我们依次来看一下。

加入依赖

 <!-- flyway -->
 <dependency>
     <groupId>org.flywaydb</groupId>
     <artifactId>flyway-core</artifactId>
 </dependency>

在项目 pom.xml 文件中加入上面的依赖即可。

增加配置

# 启用 flyway
spring.flyway.enabled=true
# 禁止清理数据表
spring.flyway.clean-disabled=true
# 是否已经有数据库
spring.flyway.baseline-on-migrate=true
# 基础版本号,依次递增
spring.flyway.baseline-version=0
# 迁移脚本的存放的位置
spring.flyway.locations=classpath:db/migration

这里因为很多情况下我们并不是一个新项目就开始使用 Flyway,而是项目在迭代中才引入的,所以上面的配置spring.flyway.clean-disabled=true 一定要禁用。上面几个配置由于已经继承到 SpringBoot 中了所以配置起来十分简单。

迁移脚本文件

脚本的命名规则按照上面说的,我们这边采用版本迁移。我们创建一个版本的 SQL 文件放到对应的类路径文件夹里面,文件名叫V1.2__create_test_table.sql,文件内容如下,然后我们启动项目。

CREATE TABLE `test_table`  (
  `id` int(11) NULL COMMENT 'ID',
  `name` varchar(255) NULL COMMENT 'Name'
);

启动过程中我们看到如下日志,显示了当前的版本,以及迁移的版本。

我们再查看数据库,首先 test_table 已经创建成功了

另外我们在查看flyway_schema_history 表,会发现已经多了一条版本数据,至此我们介入 Flyway 已经成功了。

总结

今天给大家介绍了一个数据库版本迁移的工具,这么好的工具大家赶紧用起来吧,这样在以后的版本迭代的过程中再也不会忘记执行SQL 了。这篇文章先跟大家介绍 Flyway 的使用,下篇文章我们再分享它的实现原理。

数据库迁移神器——Flyway的更多相关文章

  1. 195. Spring Boot 2.0数据库迁移:Flyway

    [视频&交流平台] àSpringBoot视频:http://t.cn/R3QepWG à SpringCloud视频:http://t.cn/R3QeRZc à Spring Boot源码: ...

  2. Java敏捷数据库迁移框架——Flyway

    1.引言 想到要管理数据库的版本,是在实际产品中遇到问题后想到的一种解决方案,当时各个环境的数据库乱作一团,没有任何一个人(开发.测试.维护人员)能够讲清楚当前环境下的数据库是哪个版本,与哪个版本的应 ...

  3. 数据库迁移框架Flyway介绍

    官方文档 https://flywaydb.org/getstarted/firststeps/api[https://flywaydb.org/getstarted/firststeps/api] ...

  4. 数据库迁移Flyway

    为什么需要Flyway 日常开发常常会遇到一些这样的场景 小红开发一个模块在本地数据库增加了两个字段,并且改动了dao层的代码提交到git.这时候小黄拉取了代码Run很可能报错. 如果在上线正式环境的 ...

  5. 数据库版本管理工具Flyway(4.0.3)---介绍(译文)

    Flyway Evolve your Database Schema easily and reliably across all your instances 简单的.可靠的升级(发展)你的数据库模 ...

  6. [jOOQ中文]3. 数据库版本管理工具Flyway

    https://segmentfault.com/a/1190000010526452 在执行数据库迁移时,我们推荐使用jOOQ与Flyway - 数据库迁移轻松. 在本章中,我们将简单的来使用这两个 ...

  7. EF Code First Migrations数据库迁移

    1.EF Code First创建数据库 新建控制台应用程序Portal,通过程序包管理器控制台添加EntityFramework. 在程序包管理器控制台中执行以下语句,安装EntityFramewo ...

  8. 2.EF中 Code-First 方式的数据库迁移

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...

  9. laravel数据库迁移(三)

    laravel号称世界上最好的框架,数据库迁移算上一个,在这里先简单入个门: laravel很强大,它把表中的操作写成了migrations迁移文件,然后可以直接通过迁移文件来操作表.所以 , 数据迁 ...

随机推荐

  1. 详解TCP一:三次握手、四次挥手

    TCP协议同样是运输层的协议,掌握TCP重点要关注这几个问题:顺序问题.丢包问题.连接维护.流量控制.拥塞控制.先解析下TCP报文段结构,相比于UDP要复杂很多. 首先还是两个端口号,对应着具体的应用 ...

  2. 来了,来了,你们要的Nginx教程来了

    一 Nginx简介 1.1 什么是Nginx Nginx是一个高性能的http和反向代理服务器,其特点是占用内存小,并发能力强.Nginx专为性能优化而开发,性能是其最重要的考量,能经受高负载的考验, ...

  3. Java中使用断言

    由于断言在Java程序中用于开发和测试阶段,考虑到以后很有可能会用到,在此先记类一下. 在Java语言中,给出了3种处理系统错误的机制: 1.抛出一个异常 2.日志 3.使用断言 什么时候使用断言呢? ...

  4. Java代码片段

    type 为Java中的任意数据类型,包括基本类型和组合类型,arrayName为数组名,必须是一个合法的标识符,[ ] 指明该变量是一个数组类型变量.例如: 这两种形式没有区别,使用效果完全一样,读 ...

  5. 【题解】cf1381c Mastermind

    序 (一道很考验思维质量的构造好题,而且需要注意的细节也很多.) 本题解主体使用的是简洁且小常数的\(O(nlogn)\)时间复杂度代码,并且包含其他方法的分析留给读者自行实现(其实是自己不会写或者写 ...

  6. stm32-HAL库串口收发

    串口发送 重写fputc函数 /* 优点 直接使用printf函数,发送数据长度无限制,不需要额外的数组空间 缺点 只能对应一个串口,暂时没想到解决方案 */ //头文件中要包含 stdio.h 然后 ...

  7. spring学习(八)事务操作

    一.事务的概念: 事务是并发控制的单位,一系列操作组成的工作单元,该工作单元内的操作是不可分割的,也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做,所有操作必须成功完成,否则 ...

  8. pv绑定pvc

    创建pvapiVersion: v1kind: PersistentVolumemetadata: name: pv003 labels: app: vnc003 namespace: vnc-spa ...

  9. 记一次mysql关于limit和orderby的优化

    针对于大数据量查询,我们一般使用分页查询,查询出对应页的数据即可,这会大大加快查询的效率: 在排序和分页同时进行时,我们一定要注意效率问题,例如: select a.* from table1 a i ...

  10. doc属性__module__属性__del__(垃圾回收)__call__方法

    __module__属性: 析构函数:del 是python的垃圾回收方法,当实例运行完的时候触发,回收资源 __call__