docs: 同步 P5 备份机制重写——DEPLOY §5 / API §13 / DATA_MODEL §7 / DEVELOPMENT §4.3
- DEPLOY §5.1: 说明 SQLite 现在是「备份交换格式」,恢复走单事务整库替换, 跨环境导入默认拒绝;§5.2 覆盖清单改为「由 metadata 派生」;§5.3 三个目录 支持环境变量覆盖及原因 - API §13: 导出/预览/应用三个接口的字段补齐(db_backend/deployment_env/ source_db_id/source_env/current_env、force_env_mismatch、pre_restore zip) - DATA_MODEL §7: pre_restore 改 .zip、补目录可覆盖说明 - DEVELOPMENT §4.3: 补三个备份目录环境变量
This commit is contained in:
+42
-11
@@ -183,25 +183,56 @@ tail -20 logs/web.log # 无 ERROR/Traceback
|
||||
|
||||
**「系统 → 数据备份 / 导入恢复」**(仅管理员):
|
||||
|
||||
- **导出**:`POST /api/system/backup/export` → sqlite 在线备份 API 做一致快照 → 打包 zip(`users.db` + `manifest.json` + 可选 `apks/*.apk`)
|
||||
- **导入**:上传 zip/`.db` → 校验预览(完整性 / 必需表 / schema 版本 / 未登记表告警)→ 确认后自动把当前库快照到 `data/backups/pre_restore_*.db`(安全网)→ 落 `data/restore_pending/` → **重启服务生效**
|
||||
- **导出**:`POST /api/system/backup/export` → 把当前库(MySQL 或回退模式的 SQLite)
|
||||
整库一致快照成一份 SQLite 归档 → 打包 zip(`users.db` + `manifest.json` + 可选 `apks/*.apk`)
|
||||
- **导入**:上传 zip/`.db` → 校验预览(完整性 / 必需表 / schema 版本 / 未登记表 / **来源环境**)
|
||||
→ 确认后自动把当前库导出一份 `data/backups/pre_restore_*.zip`(安全网,可再导入回来)
|
||||
→ 落 `data/restore_pending/` → **重启服务生效**
|
||||
|
||||
> **SQLite 在这里是"备份交换格式",不是运行时数据库。** 所以归档里永远是一个 `users.db`,
|
||||
> 无论平台连的是 MySQL 还是 SQLite —— 前端接口、校验逻辑、老备份的兼容性都不用变,
|
||||
> 也不依赖 `mysqldump` 这类外部二进制(容器是 `python:slim`,没有 MySQL 客户端)。
|
||||
|
||||
**恢复是怎么生效的**:重启时 `consume_pending_restore()` 在**单个事务内** `DELETE` 全表 +
|
||||
分块 `INSERT`,任何一步失败就回滚——当前数据保持原样,不会留下半新半旧的库。
|
||||
坏归档会被挪到 `data/backups/restore_failed_*/` 且不阻塞启动。
|
||||
|
||||
**跨环境导入默认拒绝**:备份的 manifest 里记了来源环境(`deployment_env`),
|
||||
若与当前库环境不一致(例如拿生产备份灌 dev 库),预览会弹黄框告警、直接应用会被拒绝;
|
||||
确需跨环境时在预览页勾选「允许跨环境导入」。
|
||||
|
||||
### 5.2 备份覆盖清单(红线)
|
||||
|
||||
覆盖清单 = `core/system_backup.py` 的 `SUMMARY_TABLES`,当前 12 张表:`app_meta` / `user` / `device_group` / `task_job` / `custom_action` / `apk_file` / `device` / `pending_device` / `agent_conversation` / `agent_experience` / `experience_audit` / `agent_action`。完整说明见 [DATA_MODEL.md](DATA_MODEL.md) §6。
|
||||
覆盖清单 = `core/system_backup.py` 的 `SUMMARY_TABLES`,**由模型元数据自动派生**:
|
||||
|
||||
> **新增任何持久化表,必须同步登记进该清单**——否则导出预览里看不到它,会被误判为"没有备份"(2026-09-10 动作库 `agent_action` 就踩过:数据其实在快照里,只是清单漏列)。
|
||||
> 导出侧有**覆盖自检**(登记表缺失 → `manifest.coverage_missing` + 日志告警);导入侧有**反向自检**(备份含未登记表 → 预览告警)。
|
||||
```python
|
||||
SUMMARY_TABLES = tuple(sorted(t.name for t in db.metadata.tables.values()))
|
||||
```
|
||||
|
||||
当前 12 张表:`app_meta` / `user` / `device_group` / `task_job` / `custom_action` /
|
||||
`apk_file` / `device` / `pending_device` / `agent_conversation` / `agent_experience` /
|
||||
`experience_audit` / `agent_action`。完整说明见 [DATA_MODEL.md](DATA_MODEL.md) §6。
|
||||
|
||||
> **新增一张 ORM 表,就自动进了覆盖清单**,不可能再漏(2026-09-10 动作库 `agent_action`
|
||||
> 曾因手工维护漏登记,数据其实在快照里,只是清单没列 → 被误判为"没有备份")。
|
||||
> 还需要手工做的只有:给新表补 `TABLE_LABELS` 的中文标签。
|
||||
> 导出侧有**覆盖自检**(登记表缺失 → `manifest.coverage_missing` + 日志告警);
|
||||
> 导入侧有**反向自检**(备份含未登记表 → 预览告警)。
|
||||
|
||||
### 5.3 目录与手工备份
|
||||
|
||||
| 目录 | 用途 |
|
||||
|------|------|
|
||||
| `data/backups/` | 导出临时 zip、`pre_restore_*.db`、`restore_failed_*` |
|
||||
| `data/restore_staging/` | 导入暂存(TTL 30 分钟自动清理) |
|
||||
| `data/restore_pending/` | 待生效恢复任务(重启时消费) |
|
||||
| 目录 | 用途 | 可否用环境变量改 |
|
||||
|------|------|------------------|
|
||||
| `data/backups/` | 导出临时 zip、`pre_restore_*.zip`(导入前安全网)、`restore_failed_*` | `DATA_BACKUP_DIR` |
|
||||
| `data/restore_staging/` | 导入暂存(TTL 30 分钟自动清理) | `DATA_RESTORE_STAGING_DIR` |
|
||||
| `data/restore_pending/` | 待生效恢复任务(重启时消费) | `DATA_RESTORE_PENDING_DIR` |
|
||||
|
||||
手工整目录备份 `data/` 仍可作兜底,但**整库恢复建议走内置功能**(在线一致快照 + 预恢复备份 + 重启原子生效,避免手工替换被 WAL/占用文件破坏)。
|
||||
> 这三个环境变量主要给**自动化测试**用:测试必须把恢复目录指到临时位置,
|
||||
> 否则测试造出来的"待生效恢复任务"会在服务下次重启时被当成用户的操作消费掉。
|
||||
|
||||
连 MySQL 时 `data/users.db` 及其 `-wal`/`-shm` **不再被读写**(只有回退模式才用),
|
||||
可以留作历史归档。手工整目录备份 `data/` 仍可作兜底,但**整库恢复建议走内置功能**
|
||||
(一致快照 + 预恢复备份 + 重启时事务替换)。
|
||||
|
||||
> ⚠️ 备份 zip 含**用户口令哈希与 AI 控制台 API Key(明文)**,注意保管与传输。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user