Skip to content

异构数据库资产信息模型设计:被真实数据逼出来的四层实体与三段字段

给一个内部“数据库测试资源信息服务”设计信息模型:数据源是一个服务注册目录,里面登记了 135 类资源、332 个实例、40+ 种数据库产品(关系型、MPP、缓存、大数据、图、国产库……),目标消费方是 AI agent——它要能搜到资源、看懂拓扑、拿到正确的连接信息。

这篇文章复盘模型从 v1 到 v3.3 的演进过程。它没有一版是“设计”出来的,每一版都是被真实数据打出来的。最终模型经 135 个真实条目逐条对标,零结构缺口——没有任何一个服务需要模型之外的字段。

脱敏声明:文中所有主机地址、主机名、路径均以占位符表示(如 <内网主机A>),不出现任何真实口令;数字(条目数、机器数、端口命中率)为真实统计,仅作规模参考。


一、问题:统一大宽表是条死路

Section titled “一、问题:统一大宽表是条死路”

第一直觉是设计一张统一的大宽表:host / port / database / username / password / version / topology ...。但只要把 40+ 种产品摆在一起,“同一个概念”的分歧就立刻浮现:

概念 MySQL Oracle Redis OceanBase Hive
“库” database SID / service_name / PDB db index(0-15) tenant warehouse
拓扑 主从 / MGR RAC + SCAN 哨兵 / cluster 多 zone hiveserver2 + metastore
凭据 user@host user + role + container 可无账号 / ACL user + tenant kerberos / none

统一大宽表只有两条死路:null 满天飞,或者语义失真——把 Oracle 的 PDB 硬塞进 database 字段,下游 agent 拿到一个看似统一、实则错误的模型。

第一条设计原则由此产生:一个字段要进公共内核,必须在全部产品中语义严格一致;凡有产品间语义分歧,一律下沉到产品专属层。


二、字段分层:Core / Profile / attrs 三段

Section titled “二、字段分层:Core / Profile / attrs 三段”

模型最终采用横向三段字段,每段的变更门槛和校验强度都不同:

层 职责 变更门槛 校验
Core 跨产品语义一致 + 搜索过滤依赖(标识/分类/形态/用途/约束/质量) 高(评审,API 依赖) 强 schema
Profile 产品差异(连接模型/拓扑模型/URI 拼装/解析规则),YAML 声明式 低(加一个文件) 按 profile 声明校验
attrs 自由键值:未建模信息先落此处,稳定后“转正” 零门槛 松校验

两个关键机制:

  • Profile 是声明式 descriptor,不是代码分支。每个产品家族一份 YAML,声明它的 connection 模型(Oracle 是 service_name + pdb,Redis 是 db_index,Kafka 是 bootstrap_servers[])、拓扑模型、URI 拼装规则和门控规则。新增一个产品 = 新增一个 profile 文件,解析器、门控、连接串拼装全部由 profile 驱动,不改框架代码。
  • attrs 是缓冲层,不是垃圾桶。目录里的人话注记(“3主3从1哨兵”、“默认无密码”)在没建模之前先落 attrs,数据不断流、不被门控阻塞;某个键被反复使用、语义稳定后,走 mini-RFC 流程转正为 profile 或 Core 字段。

ConnectionScope 是这套分层最好的注脚:MySQL 的 database、Oracle 的 PDB、Redis 的 db_index、OceanBase 的 tenant,在模型里是同一个实体,语义解释权归所属产品的 profile,模型层绝不做跨产品硬翻译。


三、实体分层:四层是被三批证据逼出来的

Section titled “三、实体分层:四层是被三批证据逼出来的”

3.1 Deployment 层:资产池逼出来的

Section titled “3.1 Deployment 层:资产池逼出来的”

初版模型是 Service→Component 两层。全量审计时发现:5 个 ServiceName 实际上是资产池——某分析型数据库一个条目下混着 4 个版本、分布在 4 台不同主机;某容器化 MySQL 一个条目下同主机 9 个实例。

没有 Deployment 层,agent 搜这个产品会拿到 4 个版本混杂的端点列表,无从选择。于是拆出部署单元:

Service(资源类别)
└── Deployment(部署单元:单版本·单生命周期·独立健康)★模型核心
└── Component(角色:master/tserver/scan/proxy/self…)
└── Endpoint(host:port + proto + role + is_entry)

拆分规则固化为拆分三律:版本 > 角色集群 > 端口。Deployment 层一经引入,同类场景全部自然落入:同主机多版本(某 DB2 三版本拆 3 部署)、多节点集群(RAC 2 节点 = 1 Deployment 2 Component)。

3.2 Component 层:12 个端点逼出来的

Section titled “3.2 Component 层:12 个端点逼出来的”

曾担心组件层是过度设计,直到真实数据拍在脸上:某大数据组件在一个服务条目下登记了 12 个 check——3 Master + 3 TServer,各自 RPC + WebUI 双协议。这 12 个端点精确映射 role × proto × host,模型的表达力恰好够用——“此前担心的过度,恰在此处是必需”。

反过来,单机服务不强制建组件:录入和展示允许扁平语法糖(无 components 层 = 隐式 role: self 单组件),存储、门控、查询统一归一化为组件结构。糖在边缘、核统一,下游代码零特判。

3.3 Stack 层:可选,且“宁可空栈不造假栈”

Section titled “3.3 Stack 层:可选,且“宁可空栈不造假栈””

Hive + MySQL(metastore 后端)+ HDFS(存储后端)这类跨产品配套,用可选的 Stack 层 + Deployment 间类型化关系(metastore_backend / storage_backend / entry_for)表达。

但全量实跑时发现了反面教训:178 对服务共享主机,逐对检查后绝大多数只是共租测试机(一台宿主机上跑着几十个无关容器实例),不是配套栈。结论:Stack 推断必须坚持双条件(共享主机组 + 发行版/配套标记),仅主机重叠是共租不是配套。当前数据下 Stack=0 是正确输出——这层是为真实配套场景预留的容量,不是每个服务都要背的行李。

Stack 与 Deployment 的边界用三问操作化:

  1. 成员是不同产品?→ 是 = Stack
  2. 同产品但可独立升级重启?→ 是 = Stack;否 = Deployment 内部组件
  3. 被多个部署共享(代理/DCS)?→ 独立 Deployment + entry_for 关系;否 = 并入使用方

灰区兜底原则:宁 Stack 勿大 Deployment——Stack 是松耦合加法,归类错了可以重划不丢数据;异质组件塞进 Deployment 会污染 profile 绑定。


四、双值制:目录是线索,实测才是事实

Section titled “四、双值制:目录是线索,实测才是事实”

核实轮用 TCP 探活 + SSH 登机对目录做了全量比对,结果触目惊心:目录登记的端口可信度只有约 40%(24 台可对比主机中仅 10 台登记端口与配置吻合)。错误模式足足有 7 类:登记过时、实例漏报、端点误挂、跨服务重复登记、同服务重复端点、停机与申请制混杂、资产池混杂。

应对不是“把目录改对”(你改不动别人的登记习惯),而是模型原生容纳两源差异——双值制:

endpoint:
registered_port: 6003 # 目录登记值
actual_port: 9011 # 核查实测值(配置实证)
verified_status: up
checked_at: ...

版本同理:version(登记粗值,如 19c)+ version_verified(实测细值,如 19.3.0.0.0)。版本可信度还进一步分了四级阶梯:L0 目录粗值 → L1 路径/进程(已被证伪:安装目录名不体现补丁级)→ L2 配置文件(无版本语义)→ L3 登库直查(权威)。实证案例:同一台 RAC 主机上 GI 栈实测 19.0、DB 栈登库直查 19.3——靠路径猜会把 19.3 错当 19.0。

这套设计背后的第一公理:目录 = 线索,核查 = 事实,物化后的 registry = 唯一可信产物。健康状态不落库(查询时实时读目录),慢变元信息物化(避免每次查询全网采集),核查证据追加式留痕(每条记录能回答“这条数据凭什么可信”)。


五、门控与一次纠偏事故:宁可不改,不可改错

Section titled “五、门控与一次纠偏事故:宁可不改,不可改错”

归一化之后、入库之前是三级门控:

层 校验内容
L1 结构 Schema 合法性、必填字段、ID 唯一性、枚举合法
L2 业务规则 按 profile 注册(每产品自己的必填/合法性);声称有凭据则口令非空;actual ≠ registered 必须有核查证据
L3 交叉验证 端点 TCP 探活复核、突变检测(本批 vs 上版剧变 → 疑似采集故障)、重复端点检测

裁决四级:accept / accept_with_warnings / quarantine(隔离不删除)/ reject。门控决策本身也作为 gate 字段随记录持久化——数据质量是数据的一部分。

采集规则铺开时,我们做过“自动纠偏”:发现登记端口与实测不符就自动改。规则是“主机上只有一个同产品候选端口时自动纠”。结果在一台跑着 17 个部署的共享主机上,17 个部署被全部误纠到同一个端口,62 条错误修正——全部回滚,一条没留。

教训固化为门控铁律:

actual_port 仅可来自同产品家族的实证(配置文件/探活),主机级唯一性假设不成立。自动纠偏需要证据强度门槛——宁可不改,不可改错。

此后所有端口修订降级为人工裁决:105 条“待裁决”复核后 82 条是伪问题(K8s NodePort 探活机制、跨产品共存实例、申请制正常关闭),真实待裁决收敛到约 20 条、4 类,逐条走人审。这个“105 → 20”的收敛过程本身就是一次很好的数据质量教育:异常多不等于错误多,先把伪异常分类剔除,再裁决真问题。


六、演进纪律:让“灵活调整”成为低成本常规操作

Section titled “六、演进纪律:让“灵活调整”成为低成本常规操作”

需求方最大的关切是“服务差异大、信息项多、以后可能要灵活调整”。对应的机制组合:

  • 只增不改不删:语义变化 = 新字段 + 旧字段标 deprecated,读取兼容至少保留一个主版本
  • 版本化:记录带 schema_version,profile 带 profile_version,读取端多版本兼容
  • mini-RFC:改 Core 或 profile = 一页文档(动机/影响面/金样例更新/快照测试结果)
  • 快照回归:全部 135 个真实条目的归一化产物固化为回归基准,任何模型变更必须重跑全量落盘对照——这让“会不会把老数据弄坏”从玄学变成 CI 里的一条红线

模型自身的演进史就是这套纪律的实证:从 v1 七组字段到 v3.3,经历引入 Deployment 层、组件层、Stack 层、attrs 层、双值制、usage_constraints 等多次变更,全部是加法,没有一次破坏既有数据。


七、验证方法论:用真实数据打模型,而不是用模型套数据

Section titled “七、验证方法论:用真实数据打模型,而不是用模型套数据”

整个过程中最有效的不是建模技巧,而是验证纪律。我们用了四层递进检验:

  1. 小样验证:3 个主力产品 179 条实拍数据映射,验证 Core+Profile 分层成立(并发现“完整解析率”随产品差异巨大——门控阈值因此必须按 profile 注册)
  2. 全量审计:131 个服务全量映射,发现资产池这一结构缺陷(Deployment 层的起源)
  3. 逐条落盘对照:131 个服务归类为 8 种结构模式,每类取真实条目完整落盘为模型记录,逐模式判定兼容性——同时做“过度设计检查”(每个结构元素的使用率实证)和“简陋检查”(有没有装不下的场景)
  4. 实跑磨合:写研究级原型归一化器跑全部真实数据,3 轮迭代修掉 4 类实现规则缺陷(主机识别、拆分键、产品词典、版本提取),同时证实 Stack=0 是正确输出

最后的总账:135 条目逐条对标,零结构缺口;80/131 服务有登机实测背书;所有未覆盖项(约 74 个用途空、29 个形态空、43 个活端点缺凭据)都是“模型有位、目录没写”的数据欠账,而非模型缺陷——这个区分本身也是诚实清单的价值。


如果你的场景也是“为多品种、来源不可信的资产设计信息模型”,这几条结论可以直接拿走:

  1. 公共内核的准入判据要苛刻:跨全部产品语义一致才能进 Core,有分歧就下沉 profile——宁可内核小,不可语义假
  2. 产品差异用声明式 profile 承接:加产品 = 加文件,不改框架;语义解释权归 profile,模型不做硬翻译
  3. 部署单元(单版本·单生命周期·独立健康)大概率是必需的层:资产池、多版本共存、容器实例池都靠它拆
  4. 可选层只在复杂场景现身:单机不建组件、不配套不建栈——层级是容量不是负担
  5. 不信任任何单一数据源:双值制(registered/actual)让模型原生容纳两源差异,比“努力把数据源改对”现实得多
  6. 自动纠偏要有证据强度门槛:宁可不改,不可改错;批量异常先分类剔除伪异常再裁决
  7. 演进只增不改不删 + 真实数据快照回归:让灵活调整成为低成本常规操作,而不是每次变更都提心吊胆
  8. 用真实数据打模型:小样 → 全量审计 → 逐模式落盘 → 原型实跑,四层递进;同时做过度设计和简陋双向检查

相关阅读:本站《跨 Agent 会话共享:自建 MCP-Memory-Server 方案》中 MCP 工具与 Schema 设计的取舍,与本文的信息模型分层思路一脉相承。