# 数据库迁移机制

本项目使用 SQLite 单文件部署，数据库升级由 `DatabaseInitializer` 和 `DatabaseMigrationRunner` 分工完成。

## 职责边界

- `backend/src/main/resources/schema.sql`：新库全量建表脚本，只使用 `CREATE TABLE IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS`。
- `DatabaseInitializer`：启动时执行 PRAGMA 和全量建表脚本。
- `DatabaseMigrationRunner`：启动时创建 `schema_migration` 表，并按版本执行旧库兼容迁移。
- `schema_migration`：记录已应用版本，避免重复执行同一迁移。

## 新增迁移规则

1. 在 `DatabaseMigrationRunner#migrations()` 末尾追加新的 `DatabaseMigration`。
2. 版本号只能递增，不复用、不改写已发布版本。
3. 每条迁移必须幂等：新增列前检查 `columnExists`，新增表和索引用 `IF NOT EXISTS`。
4. 不在 `DatabaseInitializer` 里写兼容 `ALTER TABLE`。
5. 涉及数据修复时，先写测试覆盖旧数据状态，再写迁移。

## 上线执行顺序

1. 停止应用服务。
2. 执行数据库备份：`./scripts/backup-db.sh`。
3. 部署新 JAR。
4. 启动应用，检查日志中 `Database migration N applied`。
5. 登录系统检查周期、用户、绩效结果、申诉和面谈数据。

## 回退预案

SQLite 对部分 DDL 回滚能力有限。生产回退不依赖“反向迁移”，而是使用停服备份恢复：

1. 停止应用服务。
2. 记录当前异常版本和启动日志。
3. 使用上线前备份恢复：`./scripts/restore-db.sh <backup-file>`。
4. 回退 JAR 到上一版本。
5. 启动服务并验证核心页面。

## 验证命令

```bash
cd backend
mvn -q -Dtest=DatabaseMigrationRunnerTest,PerformanceLifecycleIntegrationTest test
mvn -q test
```
