## 一、方案核心目标
-
- 规避应用账号高权限风险:应用仅拥有数据库 SELECT/INSERT/UPDATE/DELETE(CRUD)权限,无 ALTER/CREATE/DROP 等 DDL 权限,杜绝应用误操作表结构。
-
- 规范 DDL 管理:由 DBA 统一负责 Flyway 脚本审核、执行,确保表结构变更合规、可追溯。
-
- 保障环境一致性:应用启动时通过 Flyway 只读校验,确保本地/测试/生产的脚本版本、表结构完全一致,避免"脚本漏执行、版本不匹配"导致的线上故障。
-
- 适配现有权限体系:无需调整数据库权限分配,仅通过 Flyway 配置区分"执行角色"和"校验角色"。
## 二、核心分工(明确责任边界)
### (一)DBA 团队(高权限角色)
核心职责:负责 Flyway 脚本的审核、迁移执行、版本管理、异常处理,拥有数据库 DDL 全权限(ALTER/CREATE/DROP/INDEX 等)。
具体分工:
-
- 脚本审核:审核开发提交的 Flyway 迁移脚本(命名、语法、性能、安全性),杜绝不合理 DDL(如无索引查询、全表更新、冗余字段)。
-
- 迁移执行:在测试/预发/生产环境,使用高权限账号执行 Flyway 迁移命令,更新表结构和 flyway_schema_history 表。
-
- 版本维护:维护数据库中 flyway_schema_history 表的完整性,监控版本变更记录,排查版本冲突。
-
- 异常处理:迁移失败、版本不匹配、脚本错误等问题,由 DBA 主导排查修复(如回滚脚本、调整迁移顺序)。
-
- 权限管理:负责分配应用账号的数据库权限(仅开放 CRUD),管控高权限账号的使用。
### (二)开发团队(脚本提供角色)
核心职责:按规范编写 Flyway 迁移脚本,提交审核,配合 DBA 测试脚本,确保脚本可正常执行。
具体分工:
-
- 脚本编写:根据业务需求,编写符合 Flyway 命名规范、SQL 规范的 DDL 脚本(建表、加字段、加索引等)。
-
- 本地测试:在本地开发环境,使用测试账号(模拟高权限)执行脚本,验证脚本正确性、兼容性。
-
- 提交审核:将脚本提交至代码仓库(如 Git),发起审核流程,同步给 DBA 审核。
-
- 配合验证:DBA 执行脚本后,开发验证业务功能是否正常,确保表结构变更不影响现有功能。
### (三)应用部署团队(只读校验角色)
核心职责:配置 Spring Boot 项目的 Flyway 只读模式,确保应用启动时完成版本校验,无异常后正常启动。
具体分工:
-
- 配置部署:在应用配置文件中,配置 Flyway 只读校验相关参数(禁止自动迁移、开启校验)。
-
- 启动监控:应用启动时,监控 Flyway 校验日志,若出现版本不匹配,及时反馈给 DBA 和开发团队。
-
- 环境同步:确保应用部署包中的 Flyway 脚本,与 DBA 执行的脚本完全一致(同版本、同内容)。
## 三、完整执行流程(从脚本编写到应用部署)
### 步骤 1:开发编写 Flyway 脚本
-
- 开发根据业务需求,编写 DDL 脚本(如建表、加字段),严格遵循以下规范:
-
- 命名规范:V{版本号}__{描述}.sql(如 V1__create_user_table.sql、V2__add_user_phone_column.sql),版本号递增,无重复。
-
- 语法规范:符合 MySQL 8.0 语法,避免使用非标准 SQL;注释使用 <!-- 注释内容 -->(适配 MyBatis 规范);更新语句必须带主键条件,禁止全表更新。
-
- 性能规范:新增索引需评估性能,避免冗余索引;复杂 DDL 需附带 EXPLAIN 分析报告,确保无全表扫描。
-
- 开发在本地开发环境,使用测试高权限账号,执行脚本验证(如 flyway migrate),确保脚本可正常执行,无语法错误、无数据影响。
### 步骤 2:脚本提交与 DBA 审核
-
- 开发将编写好的 Flyway 脚本,提交至代码仓库(如 Git),放置在项目 src/main/resources/db/migration 目录下,提交时备注脚本用途、影响范围。
-
- 开发发起脚本审核流程,通知 DBA 进行审核,提交材料包括:脚本文件、本地测试报告、EXPLAIN 分析报告(复杂脚本)。
-
- DBA 审核脚本:重点检查语法正确性、权限安全性、性能合理性、版本号规范性,审核通过则进入下一步;审核不通过,反馈问题给开发,开发修改后重新提交。
### 步骤 3:DBA 执行脚本迁移(按环境顺序)
-
- 环境执行顺序:测试环境 → 预发环境 → 生产环境,确保低环境验证无问题后,再执行高环境。
-
- 执行方式(两种可选,推荐方式 1):
方式 1:使用 Flyway 命令行(高权限账号)
-
下载 Flyway 命令行工具,配置数据库连接(高权限账号、密码、URL)。
-
执行命令:flyway migrate -locations=files:///脚本存放路径(如本地路径、代码仓库路径),执行完成后,检查 flyway_schema_history 表,确认版本已记录、执行状态为 SUCCESS。
方式 2:使用数据库客户端(高权限账号)
- DBA 直接在数据库客户端(如 Navicat、DBeaver),复制 Flyway 脚本,手动执行,执行完成后,手动更新 flyway_schema_history 表(记录版本、脚本名称、执行时间、状态)。
-
- 执行后验证:DBA 执行脚本后,通知开发在对应环境验证业务功能,确认表结构变更正常,无异常。
### 步骤 4:应用配置与部署(只读校验)
- 应用部署团队,在 Spring Boot 项目的配置文件(application.yml 或 application.properties)中,配置 Flyway 只读校验参数,核心配置如下(两种格式可选):
格式 1:application.yml
```yaml
spring:
flyway:
enabled: true # 开启 Flyway(必须开启,否则不校验)
validate-on-migrate: true # 核心:启动时校验版本,不执行迁移
clean-disabled: true # 禁止清理数据库(必开,防止误删数据)
baseline-on-migrate: false # 禁止自动基线(避免创建默认基线版本)
locations: classpath:db/migration # 脚本存放路径(与开发提交的路径一致)
url: jdbc:mysql://数据库地址:端口/数据库名 # 应用数据库连接(只读/CRUD 权限)
user: 应用账号 # 仅拥有 CRUD 权限,无 DDL 权限
password: 应用密码
```
格式 2:application.properties
```properties
spring.flyway.enabled=true
spring.flyway.validate-on-migrate=true
spring.flyway.clean-disabled=true
spring.flyway.baseline-on-migrate=false
spring.flyway.locations=classpath:db/migration
spring.flyway.url=jdbc:mysql://数据库地址:端口/数据库名
spring.flyway.user=应用账号
spring.flyway.password=应用密码
```
-
应用部署:将配置好的应用包,部署到对应环境(测试/预发/生产),启动应用。
-
校验结果:
-
校验通过:应用正常启动,Flyway 日志显示"Validation successful",表示应用脚本与数据库版本一致。
-
校验失败:应用启动报错,日志显示"Validation failed",提示版本不匹配/脚本缺失,部署团队立即反馈给 DBA 和开发,排查问题(如 DBA 未执行对应版本脚本、应用脚本与 DBA 执行脚本不一致),解决后重新部署。
### 步骤 5:后期维护与异常处理
-
版本维护:DBA 定期检查 flyway_schema_history 表,清理无效版本记录,监控版本变更趋势;开发提交新脚本时,确保版本号连续,无跳跃、无重复。
-
异常处理场景:
-
脚本执行失败:DBA 立即停止迁移,排查失败原因(语法错误、权限问题、数据冲突),修复后重新执行;若已执行部分脚本,需根据实际情况回滚(如执行回滚脚本 V{版本号}__undo_xxx.sql)。
-
版本不匹配:应用启动校验失败,确认应用脚本与 DBA 执行的脚本版本是否一致,若应用脚本缺失,补充脚本后重新部署;若 DBA 未执行对应版本,DBA 补执行脚本后,重新启动应用。
-
权限异常:若应用账号误获得 DDL 权限,DBA 立即回收权限;若 DBA 执行脚本时权限不足,联系数据库管理员提升权限。
## 四、关键规范(必须严格遵守)
### 1. 脚本规范
-
版本号:按递增顺序编排(如 V1、V2、V3),禁止跳跃(如跳过 V2 直接用 V3)、禁止重复。
-
内容:仅包含 DDL 语句(建表、加字段、加索引、删字段等),禁止包含 DML 语句(INSERT/UPDATE/DELETE);若需执行 DML,单独提交 DML 脚本,由 DBA 单独执行。
-
兼容性:脚本需兼容 MySQL 8.0 版本,避免使用数据库特有语法,确保测试/预发/生产环境脚本可通用。
### 2. 权限规范
-
应用账号:仅开放 SELECT/INSERT/UPDATE/DELETE 权限,禁止授予 ALTER/CREATE/DROP/INDEX 等 DDL 权限。
-
DBA 高权限账号:仅由 DBA 团队持有,禁止泄露给开发、部署人员;定期更换密码,管控使用记录。
### 3. 环境规范
-
所有环境(开发、测试、预发、生产)的 Flyway 脚本必须保持一致,禁止不同环境使用不同版本的脚本。
-
迁移执行必须按"测试→预发→生产"顺序,禁止跳过低环境直接在生产执行脚本。
### 4. 日志规范
-
DBA 执行脚本后,保存执行日志(包括执行时间、脚本名称、版本号、执行结果),便于后续排查。
-
应用部署后,保存 Flyway 校验日志,若出现异常,及时提供日志给 DBA 和开发团队。
## 五、工具与辅助说明
-
Flyway 工具:推荐使用 Flyway Community 版本(免费),支持命令行执行、配置文件配置,满足日常迁移和校验需求。
-
代码仓库:推荐使用 GitLab/GitHub,对 Flyway 脚本进行版本控制,支持审核流程、版本回溯。
-
监控工具:可集成 Prometheus + Grafana,监控 Flyway 版本状态、迁移执行情况,出现异常及时告警。
-
回滚方案:建议为每一个 DDL 脚本,编写对应的回滚脚本(命名格式:U{版本号}__{描述}.sql),由 DBA 保存,若迁移失败,可快速回滚。
### 补充:Flyway 命令行执行脚本模板(DBA 专用)
1. 命令行执行模板(通用版,适配所有环境)
(1)基础迁移命令(执行未执行的脚本)
```bash
配置数据库连接(高权限账号),执行指定路径下的 Flyway 脚本
flyway migrate \
-url=jdbc:mysql://数据库地址:端口/数据库名?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true \
-user=高权限账号 \
-password=高权限密码 \
-locations=files:///本地脚本存放路径(如:/home/dba/flyway-scripts) \
-cleanDisabled=true \
-validateOnMigrate=true
```
(2)指定版本执行(仅执行某一个版本脚本)
```bash
flyway migrate \
-url=jdbc:mysql://数据库地址:端口/数据库名?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true \
-user=高权限账号 \
-password=高权限密码 \
-locations=files:///本地脚本存放路径 \
-target=V2 # 指定执行到 V2 版本(仅执行 V2 及之前未执行的脚本)
```
(3)查看版本状态(检查已执行/未执行脚本)
```bash
flyway info \
-url=jdbc:mysql://数据库地址:端口/数据库名?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true \
-user=高权限账号 \
-password=高权限密码 \
-locations=files:///本地脚本存放路径
```
2. 命令行参数说明(关键必看)
-
url:数据库连接地址,需拼接 SSL、时区等必要参数,避免连接失败。
-
user/password:数据库高权限账号(需拥有 ALTER/CREATE 等 DDL 权限)。
-
locations:脚本存放路径,files:/// 后接本地绝对路径(如 Windows 路径:files:///D:/flyway-scripts)。
-
cleanDisabled=true:禁止清理数据库,必加,防止误删数据。
-
validateOnMigrate=true:执行迁移前先校验版本,避免版本冲突。
-
target:指定迁移目标版本,适用于分批次执行脚本场景。
### 补充:Flyway 回滚脚本示例(适配 MySQL 8.0)
回滚脚本命名规范:U{版本号}__{描述}.sql(U 代表 Undo,与对应迁移脚本版本一致),仅支持 Flyway Pro/Enterprise 版本直接执行;Community 版本可手动执行回滚脚本。
示例 1:建表脚本的回滚(对应迁移脚本 V1__create_user_table.sql)
迁移脚本(V1__create_user_table.sql)
```sql
-- 创建用户表
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(50) NOT NULL COMMENT '用户名',
`phone` varchar(11) DEFAULT NULL COMMENT '手机号',
`status` tinyint DEFAULT 1 COMMENT '状态:1正常,0禁用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
```
回滚脚本(U1__drop_user_table.sql)
```sql
-- 回滚:删除用户表(与迁移脚本操作相反)
DROP TABLE IF EXISTS `user`;
```
示例 2:加字段脚本的回滚(对应迁移脚本 V2__add_user_email_column.sql)
迁移脚本(V2__add_user_email_column.sql)
```sql
-- 给用户表新增邮箱字段
ALTER TABLE `user`
ADD COLUMN `email` varchar(100) DEFAULT NULL COMMENT '邮箱' AFTER `phone`;
```
回滚脚本(U2__drop_user_email_column.sql)
```sql
-- 回滚:删除用户表邮箱字段(与迁移脚本操作相反)
ALTER TABLE `user`
DROP COLUMN IF EXISTS `email`;
```
示例 3:加索引脚本的回滚(对应迁移脚本 V3__create_user_phone_index.sql)
迁移脚本(V3__create_user_phone_index.sql)
```sql
-- 给用户表手机号字段加普通索引
CREATE INDEX idx_user_phone ON `user`(`phone`);
```
回滚脚本(U3__drop_user_phone_index.sql)
```sql
-- 回滚:删除用户表手机号索引(与迁移脚本操作相反)
DROP INDEX IF EXISTS idx_user_phone ON `user`;
```
回滚脚本注意事项
-
回滚脚本需与对应迁移脚本"反向操作",确保回滚后表结构恢复到迁移前状态。
-
所有回滚脚本需加 IF EXISTS 语句,避免回滚时因对象不存在报错。
-
Flyway Community 版本不支持自动回滚,DBA 需手动执行回滚脚本;Pro/Enterprise 版本可通过 flyway undo 命令自动执行。
-
回滚脚本需与迁移脚本一同提交代码仓库,由 DBA 统一管理,避免遗漏。
## 六、方案优势
-
安全可控:应用无 DDL 权限,杜绝应用误操作表结构,降低线上故障风险。
-
规范有序:DDL 脚本由 DBA 统一审核、执行,确保表结构变更合规、可追溯,避免"一人一脚本"导致的混乱。
-
环境一致:应用启动时校验版本,确保本地/测试/生产脚本、表结构完全一致,解决"本地能跑、生产报错"的问题。
-
分工清晰:DBA、开发、部署团队各司其职,责任明确,减少沟通成本,提升协作效率。
## 七、注意事项
-
脚本提交前,开发必须本地测试,避免提交无效脚本,增加 DBA 审核和执行成本。
-
DBA 执行脚本前,需备份对应数据库/表,避免脚本执行失败导致数据丢失。
-
应用部署前,需确认 DBA 已在对应环境执行完所有对应版本的脚本,避免校验失败。
-
若需新增 Flyway 脚本版本,需提前通知 DBA,避免 DBA 遗漏执行。