墨天轮接力白求恩为用户提供了免费的 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 则让这些分散证据回到同一份持续上下文中。

opsx_bethune_assets.png

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 根据第一条错误直接改动生产数据。

opsx_bethune_schedule.png

ORCL 为什么会进入 numeric 类型的 dbid

invalid input syntax for type numeric: "ORCL" 只能说明字符串进入了数值字段,不能直接判断是数据库类型错误、Loader 列序错误,还是巡检包本身错位。

Agent 按 kw_68 的路由矩阵同时收集四组证据。告警日志来自第一个应用节点,实际原始 ZIP 位于第二个节点,数据库和源码仓库又分别通过其他 Runtime 访问:

  1. 从应用日志确认失败批次为 3469,失败文件为 nirvana_db_extInst.txt,错误发生在 Loader 阶段;
  2. 从 MogDB 查询 rd_db_extinst 的真实列序和类型;
  3. 从另一个应用节点上的原始 ZIP 读取 PRIMARY 与 Data Guard 备库行,核对字段数和排列;
  4. 从 BTRobot 与 BethuneAnalysis 源码确认采集端的 DEFINE、SQL 输出顺序,以及 Loader 使用 pandas.read_csvexecute_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=orcldgopen_mode=READ ONLY WITH APPLYdatabase_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 分钟内完成了日志定位、跨资产调查、人的事实修正、数据包修复、重新上传与数据库验收。这里的“端到端”不是一条命令返回零,而是业务链路重新产出了可用报告。

opsx_bethune_issue_174.png

同一种告警,可以落在完全不同的修复面

issue_174 修改的是原始巡检包,但 Bethune 的历史 Issue 已经证明,日志中的 ERROR 并不存在统一修复动作。Opsx 必须先收敛证据,再选择操作对象:

Issue根因实际修复面业务验证
issue_51分析器错误合并多实例参数BethuneAnalysis 源码与 AD_DB_PAR 规则数据3218/3216/3220 依次执行 clear → analyzer → reporter,生成报告 2698/2699/2700
issue_144Oracle 名称字段超过 MogDB 历史列宽扩展已确认溢出的表字段至 varchar(128)重新上传成功,得到 batch 3361、report 2821
issue_173RD_DB_TRIGGER.base_object_type 的实际值超过 varchar(16)MogDB 表结构扩展至 varchar(128)batch 3460、report 2913,源文件 69 行全部落库
issue_174DG 行字段顺序与文件头不一致原始 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_41 Asset Memory 持续维护 Bethune 的双节点、日志位置、两个源码仓库、数据库依赖和近期事件。

当前 ERROR Schedule 在创建新 Issue 时直接注入 kw_68,Agent 不再从任意主机尝试日志、数据库和仓库连接。遇到 varchar 溢出,可以复用 kw_162 的证据路径;遇到原始 ZIP 结构问题,可以复用 kw_163kw_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 提供的不是一个更会回答日志的聊天窗口,而是一套能够持续发现、跨资产调查、受控修复、验证结果并积累经验的运维控制面。

opsx_bethune_knowledge.png