77 lines
7.1 KiB
Markdown
77 lines
7.1 KiB
Markdown
# SQL 切库与部署回归补充验收
|
||
|
||
## 结论与边界
|
||
|
||
北京时间 2026 年 9 月 21 日,在云服务器隔离实例补齐 MySQL/PostgreSQL 同引擎切库及部署脚本回归。正式 `/opt/smail` 未替换、正式数据未清空,共享数据库及其他项目未停止。
|
||
|
||
- [✓] MySQL/PostgreSQL 同引擎切库、内部重启及真实系统级进程重启。
|
||
- [✓] 目标账号不可用时明确停止,不回退源库;恢复账号后可以重新启动。
|
||
- [✓] 三阶段真实 SMTP 收信、IMAP/POP3 读取旧新中文正文及附件。
|
||
- [✓] 源库不再有应用连接且逻辑内容不变,配置历史完整保留在目标业务库。
|
||
- [✓] 两种 SQL 运行目录均没有 SQLite 文件。
|
||
- [✓] 验收器 55 项本地回归;云端扩大部署回归 125 项、零跳过。
|
||
- [ ] 跨引擎应用级迁移重启矩阵、复制/提交途中进程被杀后的恢复。
|
||
- [!] 其他生产门禁尚未关闭,不能据本记录宣布整个项目审计或部署验收通过。
|
||
|
||
迁移源库保留为离线证据,不是第二个活动业务库,未经许可不删除。最终运行仍是 SQLite/MySQL/PostgreSQL 三选一,业务数据与配置历史使用所选同一数据库。
|
||
|
||
## 工具与权限控制
|
||
|
||
`test/tools/runtime_sql_migration.py` 通过正式迁移 API 完成切库。目标数据库不预创建;目标账号随机生成,只服务于本轮测试。连接凭据通过标准输入或子进程环境传递,不输出到证据或命令行。
|
||
|
||
- MySQL 仅对准确的目标库授权,下划线转义,不授予全局权限。
|
||
- PostgreSQL 为创建目标库临时授予 `CREATEDB`,迁移准备完成即撤销,结束后禁止登录。
|
||
- 只锁定本轮目标账号模拟故障,不停止共享数据库、不操作正式账号。
|
||
- 独立限时网络单元保持迁移前后的网络命名空间,避免把数据库桥接随应用进程替换丢失误判为应用缺陷。
|
||
- 全表行摘要证明源库不变,配置历史按完整行比较;MySQL 对字段取十六进制并保留空值,避免二进制字段破坏摘要序列化。
|
||
|
||
结果中的 `temporary_creation_privilege_revoked=true` 对 MySQL 是无操作的通用阶段标记;MySQL 从未获得 PostgreSQL 式全局临时建库权限,不能据此宣称撤销过这种权限。
|
||
|
||
## 云端结果
|
||
|
||
| 项目 | MySQL | PostgreSQL |
|
||
| --- | --- | --- |
|
||
| 实例目录后缀 | `20260921-053754` | `20260921-054131` |
|
||
| 内部重启前后 PID | `774526`,不变 | `775325`,不变 |
|
||
| 系统重启后 PID | `774998` | `775619` |
|
||
| 故障恢复后 PID | `775106` | `775757` |
|
||
| 三阶段源/目标连接数 | 各为 `0 / 3` | 各为 `0 / 3` |
|
||
| 目标账号不可用 | MainPID 为零、failed、退出码 1 | MainPID 为零、failed、退出码 1 |
|
||
| 源/目标配置历史条数 | `1 / 1`,完整行一致 | `1 / 1`,完整行一致 |
|
||
| SQLite 文件 | 零个 | 零个 |
|
||
| OOM、资源采集错误、清理错误 | 全部为零 | 全部为零 |
|
||
|
||
实例完整路径前缀为 `/var/tmp/smail-review-runtime-`。内部重启保持 PID、InvocationID 和旧会话;系统级重启验证 PID、InvocationID 改变。待重启阶段拒绝业务写入,返回 `DATABASE_RESTART_REQUIRED`。故障阶段配置仍指向目标库;账号恢复后读写成功,新增邮件仅出现在目标库。
|
||
|
||
本地证据目录为 `test-log/production-remediation-20260921/sql-migration-runtime-evidence/`。汇总为 `sql-migration-results-20260921-053743.json`;05:57 再次核对两轮共 26 份本地与远端文件摘要,记录为 `sql-migration-recheck-20260921-055702.json`。
|
||
|
||
数据库桥接、应用和网络锚点均已停止,源/目标账号均锁定。05:57 再次查询数据库系统表,四个账号状态符合收尾要求,PostgreSQL 两个账号均不可登录且没有建库权限;远端记录为 `/var/tmp/smail-sql-account-check-20260921-055742.json`。
|
||
|
||
## 扩大部署回归:保留失败及修正过程
|
||
|
||
本地 Windows 执行 `test/deployment/test_*.py` 时,86 项中有 2 个失败和 2 个错误:Linux `fcntl` 不可用以及平台路径分隔符差异。不能把它记录为全部通过,也未通过跳过测试消除问题。
|
||
|
||
| 云端隔离目录 | 结果与原因 |
|
||
| --- | --- |
|
||
| `smail-review-python-20260921-054448` | 105 项、8 个错误;证书测试要求隔离 root 身份及文件所有权 |
|
||
| `smail-review-python-20260921-054632` | 125 项、1 个错误;隔离 Nginx 工作进程 `setuid(65534)` 返回 `EPERM` |
|
||
| `smail-review-python-20260921-055549` | 125 项、零失败、零错误、零跳过,退出零 |
|
||
|
||
诊断目录为 `/var/tmp/smail-review-capabilities-20260921-055359/`。实际 `/proc/self/status` 显示能力边界为 `0xc1`,但许可及有效集仅为 `0x41`,缺少 `CAP_SETUID`;独立 Python 降权探针与隔离 Nginx 的系统调用跟踪均复现权限错误。这里确认的是实际进程缺少能力,不推断未经验证的系统组件内部原因。
|
||
|
||
仅增加 `AmbientCapabilities=CAP_SETUID` 后,有效集恢复为原边界内的 `0xc1`,小探针成功降权至 UID 65534,随后另建空工作目录重跑完整套件通过。能力边界仍仅为 `CAP_CHOWN CAP_SETUID CAP_SETGID`;保留私有网络、只读系统、隐藏正式目录及服务控制接口、禁止新增权限等隔离属性,没有使用完整 root 能力。
|
||
|
||
最终隔离单元内存限额 96 MiB、交换限额零、CPU 25%、进程数 32、运行时限 120 秒;实际运行约 7.6 秒,内存峰值 28.3 MiB,无交换使用。真实隔离 Nginx 换证重载与失败回滚用例通过,不能扩大为正式 Nginx 或全协议换证已经完成验收。
|
||
|
||
最终日志为 `python-linux-tests-20260921-055549.log`,SHA-256 为 `05e48d2669483bcfd921af5cfd46e6db1d90e012ed77ea294a4bcb8200a07581`,已与远端文件核对。摘要为 `python-linux-result-20260921-055549.json`。测试日志中的续期提示来自受控测试路径,不证明实际申请了公网证书。
|
||
|
||
## 构建与正式环境保护
|
||
|
||
候选版本 `review-sql-migration-20260921`,构建源码标识 `375ffcabfea607690ea89e31b72cc346cfc122f3`,主程序 SHA-256 为 `6b700120e8bc0b6ca1ce723d0319852259d4aa983646bbc69c4c2fe73e88309d`。`sql-migration-build-manifest.json` 记录产物与验收工具摘要,`restart-source-manifest.json` 覆盖 610 个后端 Go 文件。
|
||
|
||
本次重新编译后端,复用此前未改动的前端与 Linux 插件资源,不声称本次再次构建前端。新增工具和测试提交为 `4844762`;它不修改应用源码,不能混淆为候选二进制已经包含不同的应用修改。
|
||
|
||
复核时正式 Smail、Nginx、MySQL、Scert、FDM、PostgreSQL 六个服务 PID 和 InvocationID 均与测试前一致,没有运行中的本轮测试单元。正式主程序摘要仍为 `c14ef1c5ba1dc2096c312c8357039a7330c985cbeac90765aed01d8151e05e1f`。用户原有 `云端全项目测试报告.md` 保持不变,不加入本次提交。
|
||
|
||
历史凭据撤销轮换、剩余静态安全告警、真实浏览器、正式管理员交互及 Windows 提权 IPC、DNS 自动续期与失败告警、外部邮箱最终收件、外部插件、长时容量与异机灾备仍需后续证据。本轮没有将其中任何一项改为通过。
|