187 lines
15 KiB
Markdown
187 lines
15 KiB
Markdown
# Round 5V-4 — Kingbase 隔离恢复、005 迁移与软件融合 QA
|
||
|
||
执行日期:2026-10-14。工作树:`boot4-iot-fusion-archive`;分支:`fix/iot-safety-hardening`。
|
||
本轮基线:`ba5dc7a6af9e6bb6b5166ef04d49af621c4f8de2`。
|
||
GitLab 已归档融合基线仍为 `feat/boot4-iot-fusion@37392144`;本轮没有 Push、Merge 或共享部署。
|
||
|
||
后续状态说明(2026-10-15):以下网络阻塞是本轮当时的真实状态,不覆盖后来已完成的恢复。
|
||
Round 5V-5 已通过跳板复核共享服务并通过新后端最小冒烟;Round 5V-6 已定位两条旧授权同步时间的
|
||
后续变化。当前功能通过、最终签署待运行隔离收口、硬件未验收的分项结论见
|
||
[Round 5V-6](ROUND5V6_FINAL_SIGNOFF.md)。本文件保留历史证据,不倒改当时结果。
|
||
|
||
**收尾状态(18:27之后):BLOCKED_NETWORK,不声明当前 SOFTWARE_QA_READY=YES。**
|
||
下列迁移、11项真实Kingbase测试、15路由及浏览器业务闭环在17:35前已实际通过并保留证据。
|
||
之后数据库连接中断(后端首条记录17:50:55,SQLSTATE08001;后续EOF),18:27独立TCP探测
|
||
192.168.139.218:22和:4321均超时。无法仅凭本机证据区分服务器离线、链路或路由原因,
|
||
未修改Mac/服务器网络、代理、服务或数据库配置。已停止本轮本机QA前端/后端/Redis,
|
||
不把端口仍监听当成数据库可用。恢复合法连接后只需重新预检、启动与关键读验收,
|
||
**005已经成功提交,不要因为断网而重复初始化、覆盖恢复或重做迁移。**
|
||
|
||
## 1. 授权与实际边界
|
||
|
||
本轮用户另行批准在 192.168.139.218 新建离线、资源受限 V9 临时恢复容器及恢复库;
|
||
只有原生备份恢复、005 演练及失败恢复通过,才能迁移独立 QA 库。
|
||
所有 Kingbase 业务写入均限定 `railwaysystem_fusion_qa_20261013`,或本轮新隔离容器中的专用恢复库。
|
||
未修改共享 `training`、独立 `iotlocks` 等数据库;目标 QA 内的 `iotlocks` 是 Schema,不是另一个数据库。
|
||
未扩大业务账号权限、修改系统网络、控制 MQTT/人脸/门锁设备、重启共享服务。
|
||
|
||
## 2. 镜像、许可、资源和共享服务
|
||
|
||
服务器只读确认:root UID0,hostname `localhost.localdomain`,NFSChina Server 4.0,
|
||
128 CPU、512 GiB 内存、可用约 372000 MiB,磁盘剩余约 535 GiB,负载低。
|
||
现有 `kingbase` 容器 `dcd88030ca5a`,4321→54321,版本 `KingbaseES V009R003C018`;
|
||
原挂载 `/opt/kingbase-docker/data` 未修改或复用。原生工具目录 `/home/kingbase/install/kingbase/bin/`。
|
||
|
||
仅复用已存在镜像 `kingbase_v009r003c018b0003_single_x86:v1`:
|
||
`sha256:540fa4d0c8f365c8d363a801404e93f8401c7bc5035ecd7b621f0dba862f2515`。
|
||
宿主机已有导入 tar 的 manifest/config 散列与 Docker image ID 相符;无 RepoDigest,
|
||
未拉取新镜像,不声称额外验证了供应商签名或生产供应链来源。
|
||
|
||
从镜像原始层读取并用原生许可工具检查:V009 企业版试用授权,180天,容器名/MAC不绑定,
|
||
未见 vCPU 限额;未改写许可、复制生产凭据或连接许可服务器。新服务实际通过原生启动许可校验。
|
||
这只证明现有获准 QA/试用范围可启动,不代表长期或生产部署许可。
|
||
参考:[Kingbase Docker 安装与许可检查](https://bbs.kingbase.com.cn/kingbase-html/v9/install-updata/install-docker/install-docker-1.html)。
|
||
|
||
新容器 `railwaysystem-qa-restore-round5v4`:
|
||
`c11ca10490c242651c0e87c2778102cd9de32cd703b48b57c26801686d4ef41f`。
|
||
实际运行过;Docker inspect 与 cgroup 实测确认 network=none、只有 lo、路由为空、
|
||
PortBindings={}、2 CPU、2 GiB memory+swap总额、pids=256、privileged=false、drop NET_RAW,
|
||
没有 Docker Socket 或正式数据卷。唯一新数据挂载:
|
||
`/opt/railwaysystem-qa-restore-round5v4/data` → `/home/kingbase/userdata`。
|
||
创建前检查 realpath、符号链接、名称和挂载冲突;专用随机凭据仅在 root0700 目录中的0600文件。
|
||
|
||
存储不是 5 GiB 硬配额。按用户允许的替代条件,独立监护进程每2秒统计任务目录、overlay及日志,
|
||
达到4 GiB或宿主机空闲低于100 GiB即核验容器身份后停止;日志有轮转上限。
|
||
实际观测用量约219 MB,远低于阈值;没有 OOM。监护实现:`scripts/qa/round5v4_storage_guard.py`。
|
||
共享 Kingbase/GitLab 的容器 ID 和启动时间一直未变(均为2026-10-06),GitLab healthy,其他服务持续运行。
|
||
本轮恢复完成后仅停止上述新容器;不删除其数据、恢复证据或备份。
|
||
首次Docker stop因镜像入口未响应而超时退出137(非OOM);仅重启该新实例后,
|
||
实际复核恢复库和原备份恢复库全量清单仍一致,再用原生sys_ctl fast正常停库(exit0),
|
||
sys_controldata确认cluster state=shut down,最后停止容器入口。没有重启共享实例。
|
||
|
||
## 3. 原生备份与实际恢复(不是文件读取替代)
|
||
|
||
备份源:`railwaysystem_fusion_qa_20261013`;原生 V9 `sys_dump` 自定义归档,
|
||
此前同一导出快照的63表清单/指纹,与本轮迁移前源库及新恢复库再次逐项匹配。
|
||
远端:`/opt/railway-fusion-qa-backup-20261014.YLjmJ0/fusion-qa-pre005-v2.dump`;
|
||
本机:`/Users/wzb/railway-fusion-qa-backup-20261014.6cgPn7/fusion-qa-pre005-v2.dump`。
|
||
380907字节,SHA256:`caa62bc985bd433b5d428b36e34d684b557c82576b69e5e5d9d348edfdf316b4`。
|
||
两份均在 Git 外受保护目录,原备份未改写、未删除。
|
||
|
||
在新实例创建 `railwaysystem_fusion_restore_round5v4`,用匹配版本 `sys_restore -O -x -1 -e`
|
||
实际恢复成功,退出0,stderr为空。Owner 映射到仅在新实例存在的 `round5v4_admin`,
|
||
不恢复源库认证配置/ACL;此为明确的恢复映射,而非遗漏生产认证。
|
||
|
||
实测恢复对象:public54表 + iotlocks9表;所有63表行数及排序行指纹一致;
|
||
892列、146索引、113约束、39序列、20扩展及Schema/默认值/触发器清单完成对账。
|
||
旧授权10条、旧指令15条,培训学员47、参训57、住宿34条。
|
||
唯一 native dump/reparse 语法差异是 `chk_external_operation_status` 的数组/元素 text cast:
|
||
只对这一个精确约束做规范化,另用原生SQL对10个允许值、4个非法值及NULL共15例验证语义无差异。
|
||
其他元数据不宽泛忽略。恢复后基本只读查询通过。
|
||
清单生成器:`scripts/qa/kingbase_manifest.sql`;受保护证据包含原生清单和JSON摘要。
|
||
|
||
## 4. 005 的隔离演练、回滚与源 QA 执行
|
||
|
||
005 SHA256:`90648b6ac67470f9a14f0795c4479dfb4811d4907e41a13ee5eeada16582b87f`。
|
||
审计完整20条语句:16项新增列、4项新增索引(含唯一意图索引);无DROP/TRUNCATE/DELETE/覆写业务数据。
|
||
|
||
隔离 V9 实际通过:
|
||
|
||
| 场景 | 实际结果 |
|
||
|---|---|
|
||
| 迁移中故意调用不存在函数 | SQLSTATE42883;全量DDL回滚,原结构和数据指纹一致 |
|
||
| 客户端在未提交005后断开 | 服务器自动回滚;结构/指纹一致 |
|
||
| 另一连接持读锁,DDL等锁500ms | SQLSTATE55P03;安全回滚,未破坏数据 |
|
||
| 005正常COMMIT | 16列/4索引、默认值、旧记录隔离均正确 |
|
||
| 同一005重复执行 | 全量结构/数据清单不变 |
|
||
| 重复意图键 | 原生唯一约束23505,事务回滚 |
|
||
| 从原备份进行失败恢复 | 在同一新容器内另建专用 recovery 库并实际恢复,完整清单与迁移前一致 |
|
||
|
||
上述为真实数据库的事务、连接中断及恢复验证;另有收尾时仅临时实例非优雅停止后的重启完整性复核,
|
||
不是对共享/源QA数据库服务器断电作测试,也不是完整灾难恢复/长期故障注入认证。
|
||
没有在源QA库上删除列/表或全库覆盖演练。
|
||
|
||
之后重新核验源数据库名/Schema、原备份SHA、63表清单均未变化、其他源库连接数0;
|
||
使用已有管理角色,不提权业务账号。设置 lock_timeout=3s、statement_timeout=30s,
|
||
显式事务及两表ACCESS EXCLUSIVE锁,在锁内再次核对原行指纹,执行相同005并COMMIT。
|
||
源 QA 的后验清单与隔离迁移后清单完全对应。旧10授权/15命令为 LEGACY/QUARANTINED、
|
||
version0、无来源环境/意图key,未转换为REAL。业务验收后17:23保存的过滤LEGACY核验摘要报告其完整原记录指纹仍一致。
|
||
该结论仅对应当时核验点;Round 5V-5之后观察到的两条sync_time变化及其旧实验写入来源,
|
||
见Round 5V-6追补,不将历史核验外推为永久不变。
|
||
一次性执行/核验代码:`scripts/qa/round5v4_database_stage.py`。不要对已在使用的QA库重跑该一次性编排。
|
||
|
||
`fusion_qa_app` 真实连接成功,现有SELECT/INSERT/UPDATE及序列权限足够全部业务测试;
|
||
无superuser/createdb/createrole、无schema CREATE。既有 sys_menu/sys_notice_read/sys_role_menu
|
||
三表仍有TRUNCATE/TRIGGER/REFERENCES旧授权:本轮未使用、未扩大,也未擅自收回,建议管理员另行最小化。
|
||
|
||
## 5. 真实 Kingbase Service / Mapper / 事务与故障恢复
|
||
|
||
`Round5v4KingbaseIntegrationTest`:11项真实Kingbase测试,使用生产XML、Service、
|
||
DataSourceTransactionManager及真实AOP事务代理;账号固定 fusion_qa_app;URL强校验仅允许目标QA库。
|
||
外部仅替换 MQTT 传输,未加载真实MQTT或人脸HTTP客户端。恢复扫描前拒绝无关READY工作。
|
||
合成 R5V4 数据保留审计,不删除原数据,不重置序列;用例后仅关闭自己的未尝试任务。
|
||
|
||
覆盖:入住、调宿撤旧建新、退宿意图;意图提交/命令创建前、命令创建/发送前、
|
||
DISPATCHING占用提交/传输结果未知三种独立JVM `Runtime.halt`,再创建新Service读取持久化状态恢复;
|
||
UNKNOWN转MANUAL_REVIEW且零盲目重发;未尝试的FAIL撤权可补偿;4线程原生行锁仅发送一次;
|
||
唯一意图冲突;入住和退宿故障注入时住宿状态与意图同事务回滚;旧撤权ACK不覆盖新授权;MOCK到REAL边界隔离。
|
||
数据库提交、Mock发送、双Mock回执均分别断言;不等于设备最终执行。
|
||
|
||
真实测试发现并修复此前未暴露的事务边界缺陷:桥接 AFTER_COMMIT 调用 REQUIRED 时仍可能
|
||
加入已提交但尚未清理的事务,命令滞留READY。现在桥接回调通过 `LockExecutionTransactions.committed`
|
||
明确在 REQUIRES_NEW 中生成命令,再由它自己的提交回调占用/发送;业务原子性仍留在原事务内。
|
||
修改位于 `TrainIotLockAuthBridgeServiceImpl.dispatchPushSafe/dispatchClearSafe`。
|
||
|
||
另通过85项选定后端回归、新增1项Boot4缺路由处理回归、12项QA工具测试及前端生产构建,
|
||
不把这些替代真实数据库结论。
|
||
|
||
## 6. 实际后端与 Chrome 验收
|
||
|
||
当前归档工程新进程,Java21.0.2 / Boot4.1.0,127.0.0.1:18096;生产前端127.0.0.1:18088;
|
||
独立Redis127.0.0.1:16389,口令随机、无持久化。不复用实验PID51901/8096或其他工程PID53305/8080。
|
||
运行JAR有SHA绑定私有副本;停机核验账本/PID出生时间/命令/cwd并等待退出,无粗暴清端口。
|
||
|
||
有效参数强制:mqtt.enabled=false、mock=true、real-device-write-enabled=false、whitelist空、
|
||
protocol-verified=false、retry-task-enabled=false、QA/OpenAPI关闭、人脸HTTP关闭且Mock、DMS关闭、Quartz不自动运行。
|
||
数据库用户名/URL固定QA,秘密只从本机0600配置及私有随机运行配置注入。
|
||
Kingbase/Druid实际探针发现URL中的socketTimeout=15被池解析为15ms;启动器移除URL超时并明确池60000ms,
|
||
同一探针实际验证60000ms。参考 [Druid 1.2.28 原始实现](https://github.com/alibaba/druid/blob/1.2.28/core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java)。
|
||
首页Kingbase分析SQL的 `::numeric` 改为等价标准CAST,消除Druid统计SQL解析异常;没有关闭SQL安全检查。
|
||
负向运行检查还发现被禁用的MQTT/QA端点会被旧全局处理器误报成HTTP200/业务500;
|
||
新增对Boot4 NoResourceFoundException的脱敏404处理,并以单元及真实HTTP复验,不注册或开放控制接口。
|
||
|
||
真实 Google Chrome155.0.8059.40(headed)管理员登录成功,getInfo/getRouters=200;
|
||
现有QA验证码配置返回 captchaEnabled=false,未改开关,不声称完成启用状态验证码挑战。
|
||
15路由逐页通过组件名、实际表格/图表、HTTP/业务code、JS错误检查:
|
||
首页Index/AdminDashboard四张真实ECharts、学员Student、教师Teacher、开班Plan、宿舍Dormitory、动态菜单住宿Accommodation,
|
||
以及9个IoT组件Group/Gateway/Device/Face/Auth/AccessLog/Command/MqttLog/ServiceConfig。
|
||
最后一轮浏览器请求仅出现127.0.0.1:18088,无外部主机;浏览器设有外发拒绝保护,未发生外部请求阻断事件。
|
||
品牌/Logo/侧边栏/动态菜单保留,无404/登录替身页;17:35前最终验收期间后端无SQL或未捕获异常。
|
||
后续网络连接异常见本报告顶部,不能将该时点的成功外推为当前在线状态。
|
||
|
||
浏览器合成 fixture `R5V4463c944c9547465b`,学号后缀S、人员P5463c94:
|
||
预分配2043 → 真UI入住 → Mock grant确认 → 真UI调房到B/新住宿2044 → 旧权revoke+新权grant确认
|
||
→ 真UI退宿 → revoke确认;两个授权1035/1036最终REVOKE版本2、CONFIRMED、sync4;
|
||
四条0011/0012命令均MOCK、CONFIRMED、网关/设备双ACK,住宿两条已退宿;UI与数据库再次一致核对。
|
||
离线回执驱动只接受该fixture的当前MOCK命令,危险HTTP回执入口未启用。
|
||
住宿履历和指令流水在真实Chrome中查看,不是仅调用API或替身页面。
|
||
|
||
前端旧页面引用模型不存在的checkInTime/checkOutTime,已改为真实assignedTime/updateTime,
|
||
标签为“分配时间/最近状态变更”;无额外DDL,不将updateTime冒充精确入住/退宿专用时间戳。
|
||
原生备份、数据库/浏览器运行日志和截图仅保存在受保护Git外/忽略目录,不提交个人资料。
|
||
|
||
## 7. 证据位置、复现与剩余边界
|
||
|
||
- 远端专用根:`/opt/railwaysystem-qa-restore-round5v4/`,含原生恢复输出、结构/行指纹、
|
||
isolated-results.json、source-migration-results.json、container-safety.json、historical-preservation.json、空间监护日志。
|
||
- 本机受保护忽略目录 `.qa-runtime/round5v4/`:同名JSON、真实Kingbase JUnit/子JVM日志、
|
||
后端/前端构建、浏览器15页结果和闭环数据验证;JUnit XML在ruoyi-train/target/surefire-reports。
|
||
- `output/playwright/`:最终首页、IoT九页(敏感数据行遮罩)、合成住宿履历/退宿/授权/指令证据;均不入Git。
|
||
- 具体构建、隔离启停、Kingbase选定测试及浏览器夹具流程见根 `DEMO_RUNBOOK.md`。
|
||
|
||
软件功能QA已通过,但当前可运行就绪状态受上述网络问题阻塞,更不代表生产发布或真实硬件验收。
|
||
仍须老师明确批准单台测试、确认真实协议校验字段/回执语义、
|
||
提供现场设备与单台白名单、核对UNKNOWN人工处置流程;门禁保持关闭。
|
||
Vue2/CLI4废弃依赖、旧历史素材/外部凭据轮换、既有账号过宽权限及长期商业许可仍须单独治理。
|
||
本轮没有远程CI/部署验证,没有数据库服务器断电测试,没有真实IoT执行证据。
|