- 开发人员将应用程序打包、按顺序汇总并整理数据库升级脚本
- DBA拿到数据库升级脚本检查、备份、执行,以完成数据库升级
- 应部署人员拿到应用部署包,备份、替换,以完成应用程序升级
用上 Flyway 之后的应用部署流程大概是这样的:
- 开发人员将应用程序打包(直接jenkins piplen 流程线构建 这时候flyway就已经在对应的环境执行了,脚本已经在库里生成了)
- 应部署人员拿到应用部署包,备份、替换,以完成应用程序升(Flyway将自动执行升级/备份脚本)—> 我们这边是Jenkins ci集成化构建部署,dockerfile构建镜像 ,k8s容器编排,在ci的过程中脚本就已经执行了,就不需要部署人员再去操作数据库了。
在我平时的团队开发中,我们的代码是有版本控制的,可以多人协作持续集成(工具也非常多)。但是数据库的脚本确实需要手动的去执行,团队内人多,你执行你的我执行我的,就会导致很多问题:
- 这台机器上的数据库处于什么状态?
- 此脚本是否已应用?
- 测试环境的数据库表结构和生产是否一致?
- 测试环境要新增一台应用实例,该如何搭建数据库,必备的数据和表结构如何快速同步?
所以工作中,经常听到测试小伙伴们抱怨,明明已经提测了,但是却出现 A环境正常运行,B环境就报错,找开发定位又花费很多时间。究其原因,大多数是因为数据库没有类似代码那样的版本控制自动化工具,导致管理混乱。
Flyway 这个数据库迁移库就是要解决这个问题的,可以帮我们根据数据库当前的状态,区分哪些脚本执行过,哪些没有执行,然后根据目标数据库的当前状态,决定应该执行哪些数据库脚本。
方案一
将flyway 单独维护在一个项目中,上线时手动操作,版本信息统一管理
项目地址flyway
目录结构以及命名规范 项目结构└─ibeautypass-ly-flyway
└─src
└─main
└─resources
└─db
└─migration
├─customer (命名规范:项目名称)
│ ├─version_1_0_0 (版本号 )
│ ├─V1_0_0_202204012042_02__create.sql (版本号 )
│ └─version_1_0_1
│ ├─V1_0_0_202204112042_02__update.sql (版本号 )
└─minapp (命名规范:项目名称)
├─version_1_0_0 (版本号 )
│ ├─V1_0_0_202204012042_01__create.sql (版本号 )
└─version_1_0_1
│ ├─V1_0_0_202204112042_01__update.sql (版本号 )

命名规范在定义初始化脚本时,版本号建议为V+(编号)+yyyymmddhhmm+组号(一组01,二组02)+ __(为双下划线)+create,例如
V1_0_0_202204012042_01__create.sql。
在定义变更版本时,版本号为 V+(编号)+yyyymmddhhmm+组号(一组01,二组02)+ __(为双下划线)+update名称,例如
V1_0_0_202204112042_01__update.sql。
:::info
注意,flyway严格按照版本号执行
:::
其中V1_0_0_202204012042_01__create.sql(初始化脚本)为项目所有的表结构与数据
-- SKU CREATE TABLE [dbo].[SM_Sku] ( [spu_id] varchar(15) NULL, [sku_id] varchar(15) COLLATE Chinese_PRC_CI_AS NULL, [delete_flag] int DEFAULT 0 NULL, [id] int IDENTITY(1,1) NOT NULL, [createTime] datetime2(0) NULL, [updateTime] datetime2(0) NULL, [createBy] varchar(30) NULL, [updateBy] varchar(30) NULL, CONSTRAINT [PK__SM_Sku__3213E83F92763DA0] PRIMARY KEY CLUSTERED ([id]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
其中V1_0_0_202204112042_01__update.sql 脚本如下
-- 历史套餐默认客户全部
update TB_Package_P set TB_Package_P.customer_scope = 0;
-- 历史套餐默认小程序不展示
update TB_Package_P set TB_Package_P.min_app_display = 1;
-- 初始化
update TB_Package_P set TB_Package_P.create_by = '000000000';
-- 初始化默认门店图片
UPDATE
TK_Entity SET Img = 'https://staticaliyun.meibangtech.com//data/门店图片.jpg'
WHERe Img IS NULL
运行方式
java -jar ibeautypass-ly-flyway-1.0-SNAPSHOT.jar
方案二将flyway整合在项目中,随项目启动自动执行sql脚本,每个项目都各自维护sql脚本
依赖配置org.flywaydb flyway-core org.flywaydb flyway-maven-plugin
spring:
flyway:
enabled: true
# sql文件存放目录
locations: classpath:db/migration
baseline-on-migrate: true
baseline-version: 0
encoding: utf-8
# 执行顺序,生产需要改为true
out-of-order: false
# 禁止clean命令
clean-disabled: true
validate-on-migrate: true
table: miniapp_schema_version
命名规范
SQL脚本文件名必须遵循以下命名规则:V[_][description] 。
版本号的数字间以下划线( )分隔开,版本号与描述间以连续的两个下划线(_ )分隔开。如V1_0_0_202204151646__update.sql.
SQL脚本文件放在启动类对应的resource目录的db/migration

| 优点 | 缺点 | |
|---|---|---|
| 方案一 | 解耦,所有的项目统一在一个项目里面管理 | 不同组上线时间节点不同,版本管理需要非常严格,学习成本较大 |
| 每次都需要单独切到这个工程执行对应分支 | ||
| 方案二 | 使用方便,维护成本较低 | 和项目高耦合 |
| 直接在jenkins构建的时候运行脚本不需要单独执行 |



