134 lines
6.4 KiB
Markdown
134 lines
6.4 KiB
Markdown
# 数据库初始方案(framework)
|
||
|
||
## 目标
|
||
- 在 `framework` 目录下建立 `db-init` 初始化目录,保存基础结构与基础数据。
|
||
- 支持从 MySQL 导出一份“初始化用”的基线数据,并在应用启动时自动检测是否已初始化;若未初始化,自动导入。
|
||
- 过程可重复、可审计、可在 `dev` 与 `server` 环境下安全运行。
|
||
|
||
## 目录结构规划
|
||
- `framework/db-init/`
|
||
- `sql/`
|
||
- `base-schema.sql`:基础库结构(表、索引、约束);可由 `mysqldump --no-data` 导出。
|
||
- `base-data.sql`:初始化数据(字典、默认角色、管理员等);可由 `mysqldump --no-create-info` 导出或手写。
|
||
- `scripts/`
|
||
- `export.ps1`:Windows 导出脚本(PowerShell)。
|
||
- `import.ps1`:Windows 导入脚本(PowerShell)。
|
||
- `export.sh`:Linux/Mac 导出脚本(可选)。
|
||
- `import.sh`:Linux/Mac 导入脚本(可选)。
|
||
- `README.md`:说明如何导出/导入、注意事项与环境变量。
|
||
|
||
## MySQL 导出策略
|
||
- 推荐使用 `mysqldump` 分离结构与数据,以便初始化时灵活控制:
|
||
- 结构:`mysqldump -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASSWORD --no-data --databases $DB_NAME > sql/base-schema.sql`
|
||
- 数据:`mysqldump -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASSWORD --no-create-info --databases $DB_NAME --tables <白名单表> > sql/base-data.sql`
|
||
- 数据白名单建议包含:
|
||
- 字典/配置表(如 `sys_dict`, `sys_config`)
|
||
- 权限/角色/菜单(如 `sys_user`(仅管理员)、`sys_role`, `sys_menu`, `sys_user_role`, `sys_role_menu`)
|
||
- 地区或静态映射表(如有)
|
||
- 机密信息与动态数据不导出:
|
||
- 排除审计日志、任务运行记录、业务动态表等。
|
||
|
||
## 导入策略
|
||
- 应用启动时进行“初始化检测”:
|
||
- 建议引入标记表:`app_init`(单行),字段 `initialized boolean`, `version varchar`,或在 `sys_config` 中维护 `init_done` 键。
|
||
- 检测逻辑:
|
||
- 若标记不存在或值为 `false`,视为未初始化。
|
||
- 若存在且为 `true`,跳过初始化。
|
||
- 导入步骤(未初始化时):
|
||
- 执行 `base-schema.sql`(若目标库为空或需校正结构时)。
|
||
- 执行 `base-data.sql`(插入/更新缺失的基线数据,注意幂等性)。
|
||
- 更新标记为已初始化,并记录版本与时间戳。
|
||
- 幂等性建议:
|
||
- 数据插入使用“存在则跳过/更新”策略(`INSERT ... ON DUPLICATE KEY UPDATE` 或先查询再写入)。
|
||
- 避免覆盖已有业务数据;仅在缺失时补充。
|
||
|
||
## Spring Boot 集成方案
|
||
- 方案 A(轻量):在后端增加初始化 Runner
|
||
- 新增一个 `@Component` 实现 `ApplicationRunner` 或 `CommandLineRunner` 的 `DataInitializer`。
|
||
- 启动时:检查标记 → 未初始化则依次执行 `sql/base-schema.sql` 与 `sql/base-data.sql`。
|
||
- SQL 执行方式:
|
||
- 直接通过 JDBC 读取并执行 SQL 文件(分号切分、事务包裹、失败回滚)。
|
||
- 或调用外部 `mysql` 命令(需服务器已安装 `mysql` 客户端,适合运维环境)。
|
||
- Profile 控制:默认仅在 `server` 或 `dev` 首次运行时启用;可通过配置 `app.init.enabled=true/false` 控制。
|
||
- 方案 B(推荐中长期):引入数据库版本管理工具
|
||
- `Flyway` 或 `Liquibase` 管理结构与数据变更;将初始化作为 `V1__base.sql` 脚本。
|
||
- 优点:变更有版本与校验,部署一致性更强;缺点:需要改造现有 SQL 并纳入流水线。
|
||
|
||
## 配置示例
|
||
- `application-server.yml` 中添加:
|
||
```
|
||
app:
|
||
init:
|
||
enabled: true
|
||
schema: classpath:db-init/sql/base-schema.sql
|
||
data: classpath:db-init/sql/base-data.sql
|
||
marker-table: app_init
|
||
marker-version: v1.0.0
|
||
```
|
||
- 路径策略:
|
||
- 若以资源方式打包,建议将 `db-init/sql` 复制到 `src/main/resources/db-init/sql`。
|
||
- 或保留在项目根并通过绝对/相对路径访问(需考虑部署路径与权限)。
|
||
|
||
## 脚本示例(Windows PowerShell)
|
||
- `framework/db-init/scripts/export.ps1`
|
||
```
|
||
param(
|
||
[string]$DB_HOST = "43.138.168.68",
|
||
[int]$DB_PORT = 3306,
|
||
[string]$DB_NAME = "frameworkdb2025",
|
||
[string]$DB_USER = "root",
|
||
[string]$DB_PASSWORD = "ylfw20230626@"
|
||
)
|
||
|
||
$env:MYSQL_PWD = $DB_PASSWORD
|
||
|
||
# 导出结构
|
||
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER --no-data --databases $DB_NAME > ../sql/base-schema.sql
|
||
|
||
# 按需导出数据(示例表名可调整)
|
||
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER --no-create-info $DB_NAME sys_dict sys_config sys_role sys_menu sys_user sys_user_role sys_role_menu > ../sql/base-data.sql
|
||
|
||
Write-Host "Export completed: base-schema.sql & base-data.sql"
|
||
```
|
||
- `framework/db-init/scripts/import.ps1`
|
||
```
|
||
param(
|
||
[string]$DB_HOST = "127.0.0.1",
|
||
[int]$DB_PORT = 3306,
|
||
[string]$DB_NAME = "platform",
|
||
[string]$DB_USER = "root",
|
||
[string]$DB_PASSWORD = "root"
|
||
)
|
||
|
||
$env:MYSQL_PWD = $DB_PASSWORD
|
||
|
||
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER $DB_NAME < ../sql/base-schema.sql
|
||
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER $DB_NAME < ../sql/base-data.sql
|
||
|
||
Write-Host "Import completed"
|
||
```
|
||
|
||
## 启动时自动初始化的实现建议(代码思路)
|
||
- 创建 `DataInitializer`:
|
||
- 读取 `app.init.enabled`;若为 `false` 则直接返回。
|
||
- 使用 `JdbcTemplate` 或 `EntityManager` 查询 `marker-table` 状态。
|
||
- 若未初始化:
|
||
- 读取并执行 `schema`、`data` 指定的 SQL 文件;分批执行并开启事务。
|
||
- 写入标记表 `initialized=true, version=marker-version, ts=now()`。
|
||
- 并发保护:
|
||
- 使用数据库锁或单例启动(例如基于 `SELECT ... FOR UPDATE` 或分布式锁)避免多实例重复初始化。
|
||
- 失败回滚与告警:
|
||
- 执行失败时回滚事务并记录日志,提示人工介入;避免部分写入。
|
||
|
||
## 运维与审计
|
||
- 对 `sql/base-data.sql` 的修改应评审并走 PR,避免带入敏感数据。
|
||
- CI 提示:
|
||
- 在 `server` 构建流水线中,可增加“初始化脚本语法检查”(如用 `mysql --dry-run` 或解析器)。
|
||
- 版本管理:
|
||
- 在 `db-init/README.md` 中记录每次更新目的与影响;或使用 `Flyway` 版本号管理。
|
||
|
||
## 下一步落地
|
||
- 我可以为你:
|
||
- 搭建 `framework/db-init` 目录与示例脚本、README。
|
||
- 在后端新增 `DataInitializer` 组件与配置项,支持 `dev/server` 下自动初始化。
|
||
- 可选集成 `Flyway`,将初始化脚本迁移为 `V1__base.sql` 并接入 CI。 |