墨天轮接力白求恩为用户提供了免费的 Oracle 巡检功能,从用户视角看,Oracle 离线巡检的操作并不复杂:在数据库环境中运行采集程序,得到一个 ZIP 巡检包,上传到 Bethune,等待平台生成分析报告。
真正复杂的是报告背后的处理链路。BTRobot 需要从不同版本、不同操作系统和不同部署架构的 Oracle 环境中采集数据库配置、对象、性能和 AWR 等信息;巡检包进入 Bethune 后,还要依次经过数据导入、规则分析和报告生成。Bethune 分析服务运行在两个应用节点上,过程数据与结果保存在 MogDB 中,采集端和分析端又分别由两套源码维护。
Oracle 数据库
→ BTRobot 离线采集
→ Oracle 巡检 ZIP 包
→ Bethune Loader 导入 MogDB
→ Analyzer 分析
→ Reporter 生成巡检报告
任何一个环节出现偏差,都可能让用户最终拿不到报告。应用日志中的一条 ERROR,背后可能是采集数据错误、ZIP 目录结构异常、Loader 解析缺陷、数据库字段宽度不足、分析规则不完整或应用源码问题。传统监控只能报告日志出现异常,维护人员仍需跨主机、数据库、数据包和代码仓库逐项还原现场。
Bethune Workspace 的 issue_174 展示了 Opsx 如何承接这项工作:Schedule 从应用日志发现异常并创建 Issue,Agent 沿 Asset Graph 跨多个 Runtime 收集证据,维护者在关键业务判断处提供正常样本,修复后的巡检包重新完成导入、分析和报告生成,经过验证的处理方法再进入 Knowledge。
一个服务故障,实际连接六个资产
Opsx 中的 svc-emcs-bethune 不是孤立的服务名称。Asset Graph 已经记录它与运行节点、数据库、采集程序和分析程序之间的关系:
repo-btrobot(Oracle 采集程序)
│ feeds_into
▼
svc-emcs-bethune(Bethune 分析服务)
├── runs_on → host-moapp-0001
├── runs_on → host-moapp-0002
├── depends_on → db-mogdb
└── source_of ← repo-bethune-analysis
这些 Asset 同时保存各自的 Runtime 映射。处理 Bethune 故障时,不同证据需要在不同位置获取:
| 调查对象 | Asset / Runtime | 用途 |
|---|---|---|
| 应用日志、原始 ZIP、上传接口 | 两个 Bethune 应用节点 | 确认错误、定位数据包、重新上传 |
| MogDB | 数据库 Runtime | 检查表结构、批次数据和最终落库结果 |
| BTRobot | 采集程序 Repo Asset | 验证 Oracle 数据如何采集并写入文件 |
| BethuneAnalysis | 分析程序 Repo Asset | 检查 Loader、Analyzer 和 Reporter 源码 |
因此,Agent 不需要根据错误字符串猜测“数据库在哪台主机”“ZIP 在哪个节点”或“应该读哪个仓库”。Opsx 先将告警绑定到 svc-emcs-bethune,再从真实资产关系和 kw_68 路由矩阵选择可以执行相应动作的 Runtime。
这正是本案例能够端到端推进的基础。单独部署在某一台应用服务器上的 Agent,只能看到该主机的日志和文件;数据库 AI、代码 Agent 或监控平台也只能看到各自的一部分。Opsx 持有完整资产关系,Issue 则让这些分散证据回到同一份持续上下文中。

Shell 负责持续发现,异常出现后才调用 LLM
Bethune 的应用日志由一个 Shell 类型 Schedule 持续检查。当前任务绑定其中一个应用节点,每 5 分钟读取一次 error.log,提取最新 ERROR 并计算指纹;同一条错误已经处理过时直接结束,只有出现新指纹才创建高优先级 Issue。
以下是根据当前 Schedule 整理的说明性伪代码。真实 Shell 使用 Opsx API 创建 Issue 和派发 Execution,具体请求与通知地址已省略:
LATEST=$(tail -n 500 "$LOG_FILE" | awk '/ ERROR /{line=$0} END{print line}')
[ -n "$LATEST" ] || exit 0
FINGERPRINT=$(printf '%s' "$LATEST" | sha256sum | awk '{print $1}')
PREVIOUS=$(cat "$STATE_FILE" 2>/dev/null || true)
[ "$FINGERPRINT" = "$PREVIOUS" ] && exit 0
# 创建绑定 Bethune 服务 Asset 的 Issue,并注入 kw_68
ISSUE_ID=$(create_issue \
--asset svc-emcs-bethune \
--knowledge kw_68 \
--description "$LOG_CONTEXT")
printf '%s' "$FINGERPRINT" > "$STATE_FILE"
dispatch_agent "$ISSUE_ID" --runner claude --read-only-triage
正常情况下,这段 Shell 按固定规则完成读取、去重和退出,不需要 LLM,也不消耗推理 Token。异常出现后,Schedule 才创建 Issue、注入 kw_68 Bethune 排障 Playbook,并派发 Claude Runner 做只读调查。当前 Schedule 还会等待分析结果并将 Issue 链接与结论发送到企业微信。
2026 年 8 月 20 日 10:27:45,Bethune Loader 在导入 nirvana_db_extInst.txt 时出现错误:
table: RD_DB_EXTINST
batch_id: 3469
invalid input syntax for type numeric: "ORCL"
referenced column: dbid
10:30:27,Schedule 创建 issue_174;10:30:28,Opsx 已将带有日志上下文和 kw_68 的任务派发给 Agent。从 ERROR 出现到进入可调查 Issue,不到三分钟。
自动派发阶段被明确限制为只读:可以查询日志、数据库、数据包和源码,但不能直接修改数据库、代码或重跑业务。修复动作需要人在 Issue 中确认后继续。这让高频检测保持确定性,也避免 LLM 根据第一条错误直接改动生产数据。

ORCL 为什么会进入 numeric 类型的 dbid
invalid input syntax for type numeric: "ORCL" 只能说明字符串进入了数值字段,不能直接判断是数据库类型错误、Loader 列序错误,还是巡检包本身错位。
Agent 按 kw_68 的路由矩阵同时收集四组证据。告警日志来自第一个应用节点,实际原始 ZIP 位于第二个节点,数据库和源码仓库又分别通过其他 Runtime 访问:
- 从应用日志确认失败批次为
3469,失败文件为nirvana_db_extInst.txt,错误发生在 Loader 阶段; - 从 MogDB 查询
rd_db_extinst的真实列序和类型; - 从另一个应用节点上的原始 ZIP 读取 PRIMARY 与 Data Guard 备库行,核对字段数和排列;
- 从 BTRobot 与 BethuneAnalysis 源码确认采集端的
DEFINE、SQL 输出顺序,以及 Loader 使用pandas.read_csv和execute_values的方式。
数据库中的 dbid 类型没有问题,Bethune Loader 也能成功导入同一个文件中的四条 PRIMARY 记录。异常只出现在第五条 DG STANDBY 记录:
# 文件头及正常记录所需顺序
DB_UNIQUE_NAME, TYPE, DBID, NAME, CREATED, ...
'orcl', 'OTHER', 155502428, 'ORCL', TO_DATE(...), ...
# 失败数据包中的 DG 行
'DG', 155502428, 'ORCL', 'orcldg', TO_DATE(...), ...
DG 行实际使用了 TYPE, DBID, NAME, DB_UNIQUE_NAME 的顺序,与文件头及 PRIMARY 行相比整体错位。Loader 按文件头建立 DataFrame 后,ORCL 最终落入数值型 dbid,因此 MogDB 拒绝写入。
源码解释了数据如何产生,数据库解释了它为什么失败,但最终修复判断还需要真实业务样本。维护者从已经成功处理的 PAC_20260820094600 巡检包中找到正确 DG 行,确认 DB_UNIQUE_NAME 应位于第一列:
'pacadg', 'DG', 344269080, 'PACS', TO_DATE(...), ...
结合 PAC 正常样本,修复方案随即收敛为字段重排,而不是增加字段:
# 修复前
'DG', 155502428, 'ORCL', 'orcldg', TO_DATE(...), ...
# 修复后
'orcldg', 'DG', 155502428, 'ORCL', TO_DATE(...), ...
这段过程体现了人的必要作用。Asset 和 Knowledge 提供确定性环境,Agent 负责跨系统取证、读取源码和验证假设;维护者提供同类正常数据的业务对照,并决定采用哪一种生产修复。AI 的判断可以被事实否定,后续计划必须随新证据调整。
修复的目标不是消除日志,而是重新生成报告
得到人工确认后,Agent 没有修改生产容器,也没有把 dbid 改成字符串来绕过错误,而是修复产生问题的原始巡检包:
保留原 ZIP 备份和校验值
→ 解压到临时目录
→ 只调整 nirvana_db_extInst.txt 中的 DG 行字段顺序
→ 保持 22 列及原顶层目录不变
→ 重新压缩为同名 ZIP
→ 异步调用 /oracle/bethune 重新上传
备份文件使用独立后缀保存,原始内容可以随时恢复。ZIP 必须保留原有顶层目录,否则 Loader 会因为文件名与内部目录不一致产生新的错误。上传使用后台异步执行并轮询结果,因为 /oracle/bethune 会同步完成 Loader、Analyzer 和 Reporter,短时间 HTTP 超时不能作为业务失败依据。
重新上传最终返回:
{"batch_id":3472,"operateMessage":"Success","report_id":2922,"success":true}
Opsx 随后继续验证最终消费者,而不是把上传接口返回成功作为唯一结论。MogDB 查询确认新批次写入五条 rd_db_extinst 数据:四条 PRIMARY 和一条 DG STANDBY;DG 记录的 db_unique_name=orcldg、open_mode=READ ONLY WITH APPLY、database_role=PHYSICAL STANDBY 均已正确对齐。新批次在 error.log 中没有同类错误,巡检报告也已经生成。
SELECT type, dbid, name, db_unique_name, open_mode, database_role
FROM rd_db_extinst
WHERE batchid = 3472;
从 Schedule 创建 Issue 到报告恢复,issue_174 在约 64 分钟内完成了日志定位、跨资产调查、人的事实修正、数据包修复、重新上传与数据库验收。这里的“端到端”不是一条命令返回零,而是业务链路重新产出了可用报告。

同一种告警,可以落在完全不同的修复面
issue_174 修改的是原始巡检包,但 Bethune 的历史 Issue 已经证明,日志中的 ERROR 并不存在统一修复动作。Opsx 必须先收敛证据,再选择操作对象:
| Issue | 根因 | 实际修复面 | 业务验证 |
|---|---|---|---|
issue_51 | 分析器错误合并多实例参数 | BethuneAnalysis 源码与 AD_DB_PAR 规则数据 | 3218/3216/3220 依次执行 clear → analyzer → reporter,生成报告 2698/2699/2700 |
issue_144 | Oracle 名称字段超过 MogDB 历史列宽 | 扩展已确认溢出的表字段至 varchar(128) | 重新上传成功,得到 batch 3361、report 2821 |
issue_173 | RD_DB_TRIGGER.base_object_type 的实际值超过 varchar(16) | MogDB 表结构扩展至 varchar(128) | batch 3460、report 2913,源文件 69 行全部落库 |
issue_174 | DG 行字段顺序与文件头不一致 | 原始 ZIP 中的数据行 | batch 3472、report 2922,4 PRIMARY + 1 DG 正确落库 |
这些修复可能涉及源码、规则数据、数据库结构或原始数据包,未来也可能需要修改采集程序。8 月 21 日在 issue_174 的后续调查中,Opsx 又沿同一上下文检查 BTRobot,确认 HP-UX 上备库参数未采集与采集端 CLASS 配置缺少 DG 有关。该结论已经定位到采集程序边界,但不能与本次已完成的数据包修复混写为“已经发布采集端补丁”。
Opsx 的价值不是让 LLM 对所有错误执行同一段自动修复,而是让资产身份、关系、Runtime、权限和证据决定下一步应操作什么。Schedule 只负责确定性发现;LLM 负责理解和推理;Agent 通过正确 Runtime 读取或修改真实资产;数据库变更、源码提交和业务重放则由明确的人工 Gate 控制。
一次修复如何缩短下一次故障
Bethune 的故障处理并没有停留在 issue_174 的对话记录中。
kw_68保存从日志、源码、数据库、ZIP 到修复判断的排障 Playbook,并固定跨 Runtime 路由矩阵;kw_69保存 clear → analyzer → reporter 的严格顺序和完成标准;kw_162记录 Oracle 字典字段与 MogDB 列宽漂移的处理方法;kw_163记录异常原始行、ZIP 备份、重打包和异步重传的通用做法;kw_174保存 DG 字段错位的触发指纹、正常与异常样本、修复命令、验证 SQL 和常见陷阱;kw_41Asset Memory 持续维护 Bethune 的双节点、日志位置、两个源码仓库、数据库依赖和近期事件。
当前 ERROR Schedule 在创建新 Issue 时直接注入 kw_68,Agent 不再从任意主机尝试日志、数据库和仓库连接。遇到 varchar 溢出,可以复用 kw_162 的证据路径;遇到原始 ZIP 结构问题,可以复用 kw_163 或 kw_174;前置问题解决后,再由 kw_69 指导业务重放。
这形成了 Opsx 所强调的 Self-Evolving 闭环:
Schedule 发现新证据
→ Issue 保存完整处理上下文
→ Asset Graph 确定调查对象和 Runtime
→ Knowledge 提供已验证的路径与边界
→ Agent + LLM 根据现场证据调整计划
→ 人在关键判断和写入动作处确认
→ 修复结果回到 Issue
→ 新经验继续更新 Memory、Article 与 Playbook
Agent 和 LLM 可以替换,某一次 Execution 也可能中断;只要资产、Issue、证据和 Knowledge 仍由平台持有,后续执行就不需要重新拼接整个环境。对于 Oracle 离线巡检这类跨应用、数据库、文件和源码的长链路业务,Opsx 提供的不是一个更会回答日志的聊天窗口,而是一套能够持续发现、跨资产调查、受控修复、验证结果并积累经验的运维控制面。
