mcpField
H
huawei-cloud-dws-io-diag

huawei-cloud-dws-io-diag

github.com/huaweicloud云与 DevOps59174 次安装2 天前更新
代码仓库

关于 huawei-cloud-dws-io-diag

面向 Huawei Cloud DWS 集群 I/O 过载诊断的 Skill,供处理告警和磁盘负载异常的人员使用。它通过三阶段决策树分析指标并生成标准诊断报告。

主要功能

  1. 01采集并分析集群指标
  2. 02区分客户侧与系统侧原因
  3. 03按规则筛选高负载节点
  4. 04生成标准诊断报告

适用场景

  1. 01排查 DWS I/O 使用率告警
  2. 02调查磁盘 I/O 负载异常
  3. 03响应用户发起的 I/O 诊断

MCP 相关

可优先调用 KooCLI(hcloud),也可使用 dws_autopilot MCP 服务查询集群、主机和指标数据;遇到网络错误时按规则切换至 MCP。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/huaweicloud/huaweicloud-skills --skill huawei-cloud-dws-io-diag

安装后在 Claude Code 中输入/huawei-cloud-dws-io-diag确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
cli-installation-guide.md
diagnosis-json-format.md
dws-mcp-installation-guide.md
iam-policies.md
IO_DIAGNOSIS_REF.md
io-background.md
metric-reference.md
output-format.md

详细介绍

Huawei Cloud DWS I/O 过载诊断技能

概述

此技能专用于诊断 DWS 集群 I/O 过载的根因。当集群触发 I/O 使用率过高告警时,会自动收集指标数据,通过三阶段决策树分析根因(客户侧/系统侧),并输出标准化诊断报告。

架构:KooCLI (hcloud) → DWS Autopilot API → 集群监控指标;MCP Server (dws_autopilot) → 同一 API 的备用通道

适用场景:

  • DWS 集群 I/O 使用率过高告警
  • 磁盘 I/O 负载异常调查
  • 用户发起的 I/O 诊断请求

典型用例:

  • “我的 DWS 集群 I/O 使用率很高,请帮忙诊断”
  • “收到 I/O 告警,集群 ID 是 xxx,请帮忙分析原因”
  • “DWS 集群磁盘 util 已满,帮忙看看是什么原因”

重要规则:所有诊断结论都必须来自工具的实际返回结果。禁止编造或臆测数值。输出只能包含诊断报告;禁止添加修复建议、输出 SQL 优化语句或使用表情符号。

背景知识:RAID 架构、I/O 关键指标阈值、三种主要 I/O 场景的指标特征和重要原则均记录在 I/O 背景知识 中。诊断前必须阅读。

前提条件

1. CLI 要求
  • KooCLI (hcloud) >= 3.2.0
  • 验证安装:hcloud version
  • 如果尚未安装或版本过低,请参阅 CLI 安装指南
2. MCP Server 配置(备用)
  • KooCLI 不可用时,使用 MCP Server 作为替代方案
  • 请参阅 MCP 安装指南
3. 身份验证配置
  • 有效的 Huawei Cloud 凭证(AK/SK 模式或 IAM Token)
  • 安全规则:
    • 切勿在对话或命令中暴露 AK/SK 值
    • 切勿要求用户在对话中直接输入 AK/SK
    • 仅使用 hcloud configure list 检查凭证状态
4. IAM 权限要求
  • dws:clusters:get、dws:clusters:list
  • dws:metricData:get、dws:hostOverview:get
  • 请参阅 IAM 策略

KooCLI 命令格式标准

命令格式
# Query metric data
hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<id> --metric_name=<name> --project_id=<pid> --offset=0 --limit=200 --from=<from_ts> --to=<to_ts>

# Query host information
hcloud DWS ListHostOverview --cli-region=<region> --project_id=<pid> --offset=0 --limit=200
工具选择策略

在 KooCLI 和 MCP Server 之间选择,优先使用 KooCLI。步骤 0 检查 hcloud 是否可用:

  • hcloud 可用(版本 >= 3.2.0)→ 后续步骤使用 KooCLI 命令行调用
  • hcloud 不可用(未安装或版本 < 3.2.0)→ 后续步骤使用 MCP Server 工具调用

回退与终止策略:

  • 选择 hcloud 后,如果首次调用返回 NETWORK_ERROR(连接超时、网络不可达等),则自动回退到 MCP Server,后续步骤均使用 MCP 模式
  • 如果 hcloud 返回 NETWORK_ERROR,且 MCP Server 也不可用(未配置或返回身份验证/连接错误),则终止此技能并输出:KooCLI network unavailable and MCP Server connection failed. Please check KooCLI network configuration or DWS Autopilot MCP Server configuration and retry
  • 选择 MCP Server 后,如果首次调用返回身份验证错误(例如 401 Unauthorized),则不要回退到 hcloud。直接终止此技能并输出:MCP Server authentication failed. Please check DWS Autopilot MCP Server authentication configuration and retry
  • 非 NETWORK_ERROR 的 hcloud 调用失败(例如参数错误、权限不足)不会触发回退;请遵循现有重试逻辑

选择工具后,应始终使用该工具,不要切换(NETWORK_ERROR 回退除外)。如果调用失败,重试一次(最多尝试 2 次)。如果仍然失败,将该指标标记为“不可用”,并继续下一步。当所有指标查询都失败时,直接生成诊断报告。

参数映射
常用参数hcloud 参数MCP 参数
区域--cli-region(内置于 MCP 连接)
项目 ID--project_idproject_id
集群 ID--cluster_idcluster_id
指标名称--metric_namemetric_name
开始时间--fromfrom_ts
结束时间--toto_ts
分页偏移量--offsetoffset
分页上限--limitlimit
排序字段(不支持)order_by
排序方向(不支持)sort_by
MCP 工具
工具名称用途关键参数
dws_autopilot_get_clusters查询集群列表project_id, cluster_id, limit, offset
dws_autopilot_get_hosts查询主机信息project_id, cluster_id, limit, offset
dws_autopilot_get_metric查询指标数据project_id, cluster_id, metric_name, from_ts, to_ts, limit, offset, order_by, sort_by

metric_data 参数说明:metric_data 不支持按 instance_name 过滤(没有此类参数);查询会返回完整的集群数据,必须根据 inst_name 字段筛选目标实例;metric_data 不支持 period 参数(采样周期由平台自动确定)。

可用的 metric_name:IOStat、CpuStat、cpu_io_diagnose_detail、business_concurrency、business_query_monitor、business_thread_wait、bussiness_conflict_lock

时间协议:from_ts/to_ts 必须使用 Unix 毫秒时间戳;所有时间均采用 UTC 时区;建议的时间窗口:从告警时间前 5 分钟到告警时间(from_ts = first_alarm_time - 300000)。

返回格式:成功时为 {"code": 0, "data": [...]};失败时为 {"code": -1, "message": "error description"}。失败时重试一次;如果仍然失败,则使用降级路径,并在报告中标记为“不可用”。

各指标的关键字段:

  • IOStat:ctime, host_id, disk_name, io_data{util, await, r_await, w_await, r_s, w_s, read_iops, write_iops, rMB_s, wMB_s, read_throughput, write_throughput, avgrq_sz, avgqu_sz} → 核心 I/O 指标
  • CpuStat:ctime, host_id, cpu_data{usr, sys, idle, iowait} → iowait > 30% 表示存在明显的 I/O 压力
  • cpu_io_diagnose_detail:ctime, host_id, active_queries[{query, query_id, userName, cpu_rate, state, inst_name, duration_ms}], io_stats{read_iops, write_iops, read_throughput, write_throughput} → I/O 诊断详情 + 活动查询
  • business_concurrency:ctime, concurrency_value, active_connections → 业务并发数
  • business_query_monitor:ctime, query, query_id, username, duration_ms, host_id → 历史实时查询
  • business_thread_wait:ctime, wait_event, count, username, host_id → 等待事件(wait wal sync、WALWriteLock 等)
  • bussiness_conflict_lock:ctime, lock_type, blocker, waiter, username, host_id → 锁冲突

各步骤的查询差异,请参阅 指标参考。

分页规范

所有工具调用(MCP 和 hcloud)都必须使用分页查询,以防止单次响应过大并超过令牌限制。

分页规则:

  • 统一使用 limit=200(不要使用 800 或其他较大的值)
  • 第一页使用 offset=0;如果返回的数据条数 = 200,则使用 offset+=200 并继续查询
  • 重复上述步骤,直到返回的数据条数 < 200,然后合并所有分页数据
  • 合并时,将所有页面的数据数组拼接成完整数据集

MCP 调用示例(使用 IOStat):

Page 1: dws_autopilot_get_metric(project_id, cluster_id, metric_name="IOStat", from_ts, to_ts, limit=200, offset=0)
If returned data length = 200:
Page 2: dws_autopilot_get_metric(project_id, cluster_id, metric_name="IOStat", from_ts, to_ts, limit=200, offset=200)
If returned data length < 200: Stop pagination, merge page 1 + page 2 data

hcloud 调用示例(使用 IOStat):

Page 1: hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<id> --metric_name=IOStat --project_id=<pid> --offset=0 --limit=200 --from=<from_ts> --to=<to_ts>
If returned data count = 200:
Page 2: hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<id> --metric_name=IOStat --project_id=<pid> --offset=200 --limit=200 --from=<from_ts> --to=<to_ts>
If returned data count < 200: Stop pagination, merge data

工作流

诊断前,请根据步骤 0-7 制定执行计划,然后按顺序执行。工具选择策略请参阅“KooCLI 命令格式标准”部分;后续步骤不再重复说明。所有 MCP 工具调用均遵循“分页规范”部分;后续步骤不再重复分页细节。

步骤 0:环境检测与参数解析

参数解析:如果用户未提供 project_id 或 region_id,则从 MCP 服务配置文件 conf/dws_config.yaml 中读取:

  • 缺少 project_id 时:执行 python -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('project_id',''))" 获取
  • 缺少 region_id 时:执行 python -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('region_id',''))" 获取
  • 如果配置文件中的对应字段也为空,则提示用户提供该参数

执行 hcloud version;版本 >= 3.2.0 → tool_mode=hcloud,否则 tool_mode=mcp。

hcloud 网络可用性探测:如果 tool_mode=hcloud,执行一个轻量级 API 调用(例如,hcloud DWS ListClusters --cli-region=<region> --project_id=<project_id> --offset=0 --limit=1)以验证网络连通性:

  • 返回正常结果或业务错误(例如,权限不足、参数错误) → 网络可用,保持 tool_mode=hcloud
  • 返回 NETWORK_ERROR → 网络不可用,回退到 tool_mode=mcp
  • 回退后,如果 MCP 也不可用 → 终止执行,提示用户检查 KooCLI 网络配置或 MCP 服务配置
步骤 1:查询 IOStat

使用指标名称为 "IOStat" 查询指标,时间窗口:from_ts=first_alarm_time - 300000,to_ts=first_alarm_time。在 MCP 模式下,使用 limit=200 进行分页查询。

Autopilot 不可用判定:返回 50201/RDS.9999 错误 → 跳过步骤 1-6,将所有指标标记为 "unavailable",直接进入步骤 7。

解析:按 host_id 和 disk_name 分组,查找每个节点上每块磁盘的最新 I/O 数据。提取每块磁盘的 util、await、r_await、w_await、r_s、w_s、read_iops、write_iops、rMB_s、wMB_s、read_throughput、write_throughput、avgrq_sz、avgqu_sz。

I/O 过载判定:是否有任意磁盘的 util > 90% 或 await > 100,或吞吐量/IOPS 达到上限。

I/O 不均衡判定:节点间 util 或 await 的偏差是否 > 20%。

TOP 节点筛选:找出 I/O 负载最高的两个节点。

现象分布判定:判断节点是单块磁盘 I/O 高,还是所有磁盘 I/O 都高(用于步骤 4 的场景路由)。

高 I/O 时间点:从 IOStat 时间序列数据中,找出前 2 个 I/O 节点上任意磁盘 util > 90% 的所有 ctime 时间点。将这些 ctime 值收集为 high_io_ctimes(毫秒时间戳列表)。同时记录 util 最高时对应的 ctime,作为 peak_io_ctime。如果没有 ctime 的 util > 90%,则 high_io_ctimes 为空,peak_io_ctime 为 util 值最高时对应的 ctime。

输出:io_by_host_disk、io_by_host、max_io_hosts、problem_host_id、problem_host_util、problem_host_await、problem_host_avgrq_sz、problem_host_avgqu_sz、cluster_avg_util、is_imbalanced、io_deviation、high_io_nodes、single_disk_high_nodes、all_disk_high_nodes、high_io_ctimes、peak_io_ctime

步骤 2:获取主机名称

调用主机信息查询(MCP 模式下使用 limit=200 分页查询),构建 host_id → {host_name, ip} 映射表。仅查询步骤 1 输出中 max_io_hosts 涉及节点的主机信息。

输出:host_id_to_info_map、problem_host_ip、node_name

步骤 3:查询 CpuStat

使用指标名称为 "CpuStat" 查询指标。在 MCP 模式下,使用 limit=200 进行分页查询。

解析:提取每个节点的 iowait。iowait > 30% 表示 I/O 压力显著。iowait 高但 CPU 使用率低 → 典型的 I/O 瓶颈。

输出:cpu_by_host、high_iowait_nodes

步骤 4:三阶段决策树 I/O 场景判定

根据步骤 1 的 IOStat 数据和步骤 3 的 CpuStat 数据,通过三阶段决策树判定 I/O 场景。

前置条件:await 是否持续 > 100,且 avgqu_sz 是否持续 > 100?

  • 否 → 偶发的 await/avgqu_sz 峰值属于正常情况,无需判定场景,标记为正常
  • 是 → 进入三阶段判定

阶段 1:明确的 I/O 异常 — IOPS 和吞吐量是否远低于最低规格?

  • SSD:rMB/s+wMB_s << 900MB/s 且 r/s+w/s << 8000/s
  • HDD:rMB/s+wMB_s << 250MB/s 且 r/s+w/s << 1000/s
  • 是 → 确认为 I/O 异常(明确的硬件问题)

阶段 2:明确的 I/O 过载 — IOPS 或吞吐量是否超过最高规格?

  • SSD:rMB/s+wMB_s > 3500MB/s 或 r/s+w/s > 20000/s
  • HDD:rMB/s+wMB_s > 800MB/s 或 r/s+w/s > 2000/s
  • 是 → 确认为 I/O 过载(区分吞吐量过载、IOPS 过载或双重过载)
    • 仅吞吐量超过最高规格 → I/O 吞吐量过载
    • 仅 IOPS 超过最高规格 → IOPS 过载
    • 两者均超过最高规格 → 双重过载

阶段 3:灰区 — I/O 是否接近最低规格,或超过最低规格但低于最高规格?

  • 单个磁盘性能较差(await/avgqu_sz 高),其他磁盘正常 → 判定为 I/O 异常
  • 单个磁盘 I/O 量高(吞吐量/IOPS 高),其他磁盘正常 → 判定为 I/O 过载
  • 所有磁盘表现一致 → 与其他节点的 I/O 进行比较
    • 其他节点存在 I/O 压力但没有 I/O 等待 → 判定此节点存在 I/O 异常
    • 其他节点存在 I/O 压力和等待 / 其他节点没有 I/O 压力且没有等待 → 无法明确判定,必须提供 I/O 过载和 I/O 异常两种完整排查方向
    • 无法获取其他节点数据 → 必须建议用户提供其他节点的 iostat 数据进行比较,同时提供两种完整排查方向

现象分布判定(基于步骤 1 的 IOStat 数据,按 host_id + disk_name 维度分析):

  • 单节点 + 单磁盘 I/O 高:仅一个节点上的一块磁盘存在 I/O 异常,该节点上的其他磁盘正常或负载较低 → 数据倾斜 / 磁盘故障
  • 单节点 + 所有磁盘 I/O 高(过载型):一个节点上的所有磁盘吞吐量/IOPS 均超过限制 → 优先怀疑节点级异常(RAID 卡读写策略降级 / RAID 卡 CC 校验 / RAID 卡故障),因为 DWS 数据按磁盘分布,不会导致所有磁盘同时过载;同时将 I/O 过载排查方向作为可能性 B 提供
  • 单节点 + 所有磁盘 I/O 高(异常型):一个节点上的所有磁盘吞吐量/IOPS 均低于限制,但 await 极高 → 归类为 I/O 异常(单节点 + 所有磁盘)
  • 多个节点 / 所有节点 + 所有 DN 数据磁盘 I/O 高 → 业务层过载(全表扫描、批量导入等)
  • 系统盘 I/O 高 → pg_log 日志 / pg_audit 审计日志 / 系统级任务

I/O 类型判定(用于过载场景归类):

  • wMB/s >> rMB/s → 写 I/O 为主
  • rMB/s >> wMB/s → 读 I/O 为主

输出:io_scenario、io_type、phenomenon_distribution、is_gray_zone、gray_zone_result

步骤 5:查询业务并发量和 I/O 诊断详情

5a:查询业务并发量

调用指标查询,metric_name="business_concurrency"。在 MCP 模式下,使用 limit=200 进行分页查询。

输出:max_concurrency、avg_concurrency、is_high_concurrency

5b:查询前 2 个节点的 I/O 诊断详情

调用 dws_service_autopilot_metric_data,参数与步骤 3 相同,将 metric_name 改为 "cpu_io_diagnose_detail"。注意:metric_data 不支持按 host_id 筛选;查询会返回整个集群的数据,然后按前 2 个 I/O 节点的 host_id 进行筛选。 分页查询:此指标的数据量最大(多节点 × 多实例 × 多时间点 × 多查询),单页 800 条可能不够。第一页设置 offset=0、limit=800;如果返回的数据条数 = 800,则 offset+=800 并继续查询,直到返回的数据少于 800 条,然后合并所有分页数据。

高 IO 时段筛选:从返回的数据中,仅保留 ctime ∈ {{steps.iostat_metrics.output.high_io_ctimes}} 的采样点,排除正常时段内无关的查询。如果 high_io_ctimes 为空(无高 IO 时段),则取 util 最高时刻的数据,并标注为“IO 未持续超过阈值,以下为 IO 最高时刻的查询参考”。

解析返回的数据,为每个节点提取:

  • 活跃查询语句列表(SQL)
  • 执行用户(userName)
  • 查询耗时(duration_ms)
  • 每条 SQL 的 IO 消耗(io_read、io_write,由 pidstat -t -d 采集)
  • IO 统计信息(io_stats:read_iops、write_iops、read_throughput、write_throughput)
  • 锁等待状态

落盘判定规则:根据活跃语句的特征进行推断,若满足以下任一条件,则标记 spill_detected=true:

  • SQL 语句包含多表 JOIN 以及排序(ORDER BY)/聚合(GROUP BY/DISTINCT)操作,且写 IO 显著高于读 IO(当 io_data_available=true 时,io_write >> io_read,或 io_stats.write_throughput 异常高)
  • business_thread_wait 包含 wait file write 等待事件
  • 将匹配的 SQL 记录到 full_scan_queries(复用此字段记录落盘 SQL),spill_info 记录第一条落盘 SQL 的详细信息

全表扫描判定规则:根据活跃语句的特征进行推断,若满足以下条件,则标记 full_scan_detected=true:

  • SQL 语句是针对大表的 SELECT /COUNT()/MAX/MIN 等聚合查询,且 WHERE 条件过滤效果差(没有 WHERE,或仅包含非等值条件)
  • 将匹配的 SQL 记录到 full_scan_queries

数据倾斜推断规则:根据 IOStat 的节点间 IO 偏差进行推断,此判断不作为确认结论:

  • 如果 IOStat 显示某节点的 util 显著高于其他节点(偏差 > 20%),且该节点上的活跃查询集中于少数几张表,则 is_data_skewed=true
  • skew_info 记录偏差最大的两个节点和偏差百分比,描述标注为“根据节点间 IO 偏差推断,可能存在数据倾斜,建议检查表的分布列” IO 贡献 TopN 统计规则(时间窗口聚合,与 DMS 监控项逻辑对齐):
  • 数据可用性判定:检查所有 active_queries 的 io_read/io_write 字段,如果这些字段全为 0 或不存在,则 io_data_available=false。注意:io_data_available=true 是一种罕见情况(仅当集群节点部署了 pidstat 采集插件且采集正常时,io_read/io_write 才会有非零值;大多数情况下此字段为 0),因此通常 io_data_available=false
  • 过滤阈值(与 DMS 插件过滤逻辑对齐,io_read/io_write 单位为 kB/s):仅当 cpu_rate < 20% 且 io_read < 1024 且 io_write < 1024 时,才过滤该行(AND 关系,三项均低于阈值才过滤,任意一项超出阈值则保留),保留的行参与 TopN 统计
  • Ruby 用户过滤:userName 为 "Ruby" 的行不参与 TopN 排序(与 DMS 监控项逻辑对齐),Ruby 的 IO 消耗体现在系统侧根因描述中
  • 跨采样点聚合:按 query_id 分组,在高 IO 时段内跨多个采样点聚合(io_read/io_write 是速率值,单位为 kB/s):
    • IO 总量:Σ(io_read + io_write),反映时间窗口内的累计 IO 贡献
    • CPU 总量:Σ(cpu_rate),反映时间窗口内的累计 CPU 贡献
    • 出现频率:该 SQL 出现的采样点数 / 高 IO 时段的总采样点数,例如 3/3,反映持续性
  • TopN SQL IO 贡献:
    • 当 io_data_available=true 时:从按 SQL 聚合的行中(lwtid 非空且 userName 不是 "Ruby"),按 IO 总量降序排序,取前 3 名;次级排序依据为出现频率降序。提取 query_preview、query_id、userName、total_io_read、total_io_write、frequency、cpu_rate、io_characteristic
    • 当 io_data_available=false 时:从按 SQL 聚合的行中(lwtid 非空且 userName 不是 "Ruby"),按 CPU 总量降序排序,取前 3 名;次级排序依据为出现频率降序。提取 query_preview、query_id、userName、total_cpu_rate、frequency、cpu_rate、io_characteristic。标注为“IO 消耗数据不可用,按 CPU 占用排序作为参考”
  • TopN 用户 IO 贡献:
    • 当 io_data_available=true 时:从按用户聚合的行中(lwtid 为空且 userName 非空且 userName 不是 "Ruby"),按 IO 总量降序排序,取前 3 名;次级排序依据为出现频率降序。提取 userName、total_io_read、total_io_write、frequency
    • 当 io_data_available=false 时:从按用户聚合的行中(lwtid 为空且 userName 非空且 userName 不是 "Ruby"),按 CPU 总量降序排序,取前 3 名;次级排序依据为出现频率降序。提取 userName、total_cpu_rate、frequency。标注为“IO 消耗数据不可用,按 CPU 占用排序作为参考”

时间标注规则:cpu_io_diagnose_detail 返回的 ctime 是 Autopilot 采集快照时间,并非 SQL 的实际开始时间。如果 active_queries 包含 duration_ms 字段,则 SQL 开始时间 = ctime - duration_ms,标注为“开始时间”;如果没有 duration_ms,则直接使用 ctime,标注为“采集时间”(不要将采集时间标注为“开始时间”)。

活跃用户统计规则:仅统计 state=active 的用户和连接;不统计 idle 状态。按 userName 分组并统计活跃查询数量,识别排名靠前的用户。

输出(steps.top_node_io_diagnose.output):

io_query_details:           # Node IO query details [{host_id, queries, io_stats}]
spill_detected:             # Whether spill to disk is detected (boolean)
spill_info:                 # Spill information {query, query_id, username, host_id, io_write_rate}
full_scan_detected:         # Whether full table scan is detected (boolean)
full_scan_queries:          # Full table scan query list [{query, query_id, username, host_id, duration_ms}]
is_data_skewed:             # Whether data skew is possible (inferred from IOStat inter-node deviation, non-confirmatory) (boolean)
skew_info:                  # Skew inference information {max_deviation_node, min_deviation_node, deviation_pct, description} (inferred from IOStat inter-node IO deviation, marked when deviation > 20%, cannot confirm specific table names)
topn_sql_io:                # Top3 SQL IO contribution (time window aggregation) [{query_preview, query_id, user_name, total_io_read, total_io_write, frequency, cpu_rate, io_characteristic}]
topn_user_io:               # Top3 User IO contribution (time window aggregation) [{user_name, total_io_read, total_io_write, frequency}]
io_data_available:          # Whether io_read/io_write data is available (boolean)
peak_io_ctime:              # Highest util time point ctime in high IO time period

5c:查询等待事件和锁冲突

使用 metric_name="business_thread_wait" 和 metric_name="bussiness_conflict_lock" 调用指标查询。在 MCP 模式下,使用 limit=200 进行分页查询。

解析:识别与 I/O 相关的等待事件(例如 wait wal sync、WALWriteLock、I/O wait)。识别导致 I/O 异常的锁冲突。

输出:wait_events、io_wait_detected、lock_conflicts、lock_conflict_detected

步骤 6:分析诊断结果

根据步骤 1-5 收集的数据,结合步骤 4 的三阶段决策树结果和现象分布,转至相应场景并执行完整的调查方向分析。

时间格式:所有 Unix 毫秒时间戳(first_alarm_time、ctime 等)均使用 UTC 时区。在报告中,必须将其转换为北京时间(UTC+8)字符串 YYYY-MM-DD HH:MM:SS。可以使用 python -c "from datetime import datetime,timezone,timedelta; print(datetime.fromtimestamp({ms}/1000,tz=timezone(timedelta(hours=8))).strftime('%Y-%m-%d %H:%M:%S'))"。不要在脑中计算时间戳值。

用户身份判断(基于数据库用户,即 cpu_io_diagnose_detail username):

  • 数据库用户为 "omm" 或 "Ruby" → 系统原因
  • 数据库用户既不是 "omm" 也不是 "Ruby" → 客户侧原因
场景路由与完整调查方向

根据步骤 4 的 io_scenario 和 phenomenon_distribution,转至相应场景并执行完整调查。必须阅读 IO_DIAGNOSIS_REF.md,了解完整的场景路由表、调查方向列表、客户侧/系统原因说明和输出示例;不得仅依据下方的场景概述进行分析。

场景概述:

  • 场景 1:I/O 吞吐量过载 → 按读 I/O/写 I/O 路由,子场景按现象分布路由
  • 场景 2:IOPS 过载 → 按读 I/O/写 I/O 路由,调查碎片 I/O(avgrq_sz<30),子场景按现象分布路由
  • 场景 3:I/O 异常 → 调查硬件层(RAID 卡/I/O 调度器),不依赖活跃语句
  • 场景 4:双重过载 → 合并场景 1 和场景 2 的调查方向,并去重重叠方向
  • 灰色区域 → 同时输出 I/O 过载和 I/O 异常的完整调查方向

综合判断规则:

条件标记
problem_host_util > 90%磁盘利用率过高
problem_host_await > 100I/O 响应时间过长
io_deviation > 20%集群 I/O 负载不均衡,可能存在数据倾斜
is_high_concurrency = true and spill_detected = true高并发导致数据溢出到磁盘,引起 I/O 过高
full_scan_detected = true全表扫描导致 I/O 过高,已识别具体语句
io_wait_detected = true检测到 I/O 相关等待事件
lock_conflict_detected = true锁冲突影响 I/O 性能
统计与聚合要求:
  1. 当 io_data_available=true 时:使用 Step 5b 时间窗口聚合结果(按 high IO 时段内的采样点按 query_id 聚合,主要排序依据为 Σ(io_read+io_write) 降序,次要排序依据为出现频率降序),分别取 Top3 SQL 和 Top3 用户 IO 贡献。过滤阈值(AND 关系):仅当 cpu_rate<20% 且 io_read<1024kB/s 且 io_write<1024kB/s 时,过滤掉该行。Ruby 用户不参与 TopN 排序,其 IO 消耗反映在系统侧根因描述中(例如,“系统用户 Ruby 的 autovacuum 任务导致高 IO”)。在报告中输出【IO 贡献 Top3 SQL】和【IO 贡献 Top3 用户】,包括总 IO(单位为 kB,在报告中换算为 MB)和出现频率。TopN SQL 条目应包含 IO 特征(spill/全表扫描/高 IO 等待等定性描述),不单独设置【IO 相关异常查询】部分,以避免同一 SQL 重复出现
  2. 当 io_data_available=false 时(io_read/io_write 全部为 0 或不存在):使用 Step 5b 时间窗口聚合结果,但排序依据改为 Σ(cpu_rate) 降序,而非总 IO,分别取 Top3 SQL 和 Top3 用户贡献。过滤阈值:仅当 cpu_rate<20% 时,过滤掉该行。Ruby 用户不参与 TopN 排序。在报告中输出【IO 贡献 Top3 SQL】和【IO 贡献 Top3 用户】,并注明“IO 消耗数据不可用,按 CPU 占用排序作为参考”。TopN SQL 条目包含 query_preview、query_id、userName、total_cpu_rate、frequency、cpu_rate、io_characteristic。TopN 用户条目包含 userName、total_cpu_rate、frequency。此外,将检测到的 IO 相关现象描述为调查方向:spill 特征、全表扫描特征、IO 等待事件。这些是可能性推断,而非 IO 消耗的量化证据,应注明为“调查方向”
  3. gaussdb 进程的 IO 开销应合并到相应的根因描述中,不要作为独立说明列出

无异常判定:当 Step 4 三阶段决策树判定 I/O 场景正常时(即无需进行场景判定,util 远低于 90%、await 远低于 100ms、iowait 远低于 30%),则 io_scenario=normal,无需进行场景路由,诊断结论为“诊断未发现异常”。此时:

  • root_cause_category = "normal",io_scenario = "normal",其他所有标志(spill_detected、full_scan_detected、io_wait_detected、lock_conflict_detected、is_data_skewed)= false
  • io_investigation_info = 空
  • 仍按 Step 5b TopN 统计规则计算 topn_sql_io 和 topn_user_io,并注明这些是参考信息,而非根因证据
  • 报告中的“问题节点 I/O 概览”表应为空(无行),因为没有节点超过阈值
  • “IO 相关异常查询和调查信息”部分应显示当前活跃查询参考信息(而非调查方向),并注明“IO 未发现异常,以下为当前活跃查询参考信息”
  • “IO 贡献 Top3 SQL”和“IO 贡献 Top3 用户”部分应显示当前活跃查询/用户参考信息,遵循与异常场景相同的 io_data_available=true/false 呈现规则,但注明这些是参考信息,而非根因证据

输出:root_cause_category、io_scenario、phenomenon_distribution、io_type、summary、specific_sql、is_data_skewed、spill_detected、full_scan_detected、io_wait_detected、lock_conflict_detected、io_investigation_info、topn_sql_io、topn_user_io、io_data_available

步骤 7:生成诊断报告

按照“输出格式”部分中的模板生成 HTML 报告。生成报告后,将 HTML 文件保存到当前工作目录(工作区根目录),文件名为 dws_io_diagnosis_report_{timestamp}.html,其中 {timestamp} 为当前机器的本地时间,格式为 yyyyMMdd_HHmmss(例如:dws_io_diagnosis_report_20260623_150421.html)。

除 HTML 报告外,还需输出 {{diagnosis_json}} 数据结构。必须阅读 diagnosis_json 格式参考,了解完整的数据结构、内容字段格式规则(io_data_available=true/false)、系统侧/无异常示例以及 Ruby 用户约束。

无异常情况的报告章节填充规则:

  • 当 io_scenario=normal(诊断结论为“未检测到异常”)时:
    • diagnosis_summary:输出 <div class="conclusion-item normal">诊断暂未发现异常</div><div class="conclusion-item normal">诊断时间范围: {from_time} ~ {to_time}</div>
    • 问题节点 I/O 概览表:仅输出表头行,不输出数据行(因为没有节点超过阈值)
    • io_investigation_content:显示当前活跃查询的参考信息,并标注为“IO未发现异常,以下为当前活跃查询参考信息”。遵循与异常情况相同的 io_data_available=true/false 渲染规则,但将“IO排查方向”替换为“IO参考信息”,并标注为参考信息,而非排查方向
    • topn_sql_io_content 和 topn_user_io_content:遵循与异常情况相同的 io_data_available=true/false 渲染规则,但标注为参考信息,而非根因证据
    • diagnosis_json:content = "诊断暂未发现异常",addition.advice = "暂无"
  • 当 io_scenario 非 normal(检测到异常)时:
    • 问题节点 I/O 概览表:仅列出 I/O 超过阈值的节点,不列出正常节点
    • io_investigation_content:按照 io_data_available=true/false 规则填写

核心命令

查询集群列表
# hcloud
hcloud DWS ListClusters --cli-region=<region> --project_id=<pid> --offset=0 --limit=200
# MCP
dws_autopilot_get_clusters(project_id=<pid>)
查询主机信息
# hcloud
hcloud DWS ListHostOverview --cli-region=<region> --project_id=<pid> --offset=0 --limit=200
# MCP
dws_autopilot_get_hosts(project_id=<pid>, cluster_id=<cid>, limit=200, offset=0)
查询指标数据(通用格式)
# hcloud
hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<cid> --metric_name=<name> --project_id=<pid> --offset=0 --limit=200 --from=<from_ts> --to=<to_ts>
# MCP
dws_autopilot_get_metric(project_id=<pid>, cluster_id=<cid>, metric_name=<name>, from_ts=<from>, to_ts=<to>, limit=200, offset=0, order_by="ctime", sort_by="desc")

参数确认

参数必填/可选描述默认值
alarm_serial_number必填告警序列号N/A
cluster_id必填集群 IDN/A
first_alarm_time必填首次告警时间(毫秒时间戳)N/A
alarm_name必填告警名称N/A
project_id可选项目 ID从 MCP Server 配置文件(conf/dws_config.yaml)的 project_id 字段读取
region_id可选区域标识符从 MCP Server 配置文件(conf/dws_config.yaml)的 region_id 字段读取
node_name可选告警节点名称空(集群级告警)
cluster_name可选集群名称使用 cluster_id
alarm_severity可选告警级别N/A

参数解析规则:如果用户未提供 project_id 或 region_id,则从 MCP Server 配置文件 conf/dws_config.yaml 中读取:

  • project_id:从 conf/dws_config.yaml 中读取 project_id 字段
  • region_id:从 conf/dws_config.yaml 中读取 region_id 字段
  • 读取方式:project_id 使用 python -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('project_id',''))",region_id 使用 python -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('region_id',''))"

输出格式

严格按照 输出格式 中的模板输出并返回。不要分析或总结模板内容,不要省略任何部分,也不要修改模板结构。输出必须与模板一致。

最佳实践

  1. 时间戳处理:first_alarm_time 已经是毫秒时间戳;直接将其用于工具参数。不要先转换为时间字符串,再转回时间戳(以避免出现 8 小时偏差)
  2. 工具选择:在 KooCLI 和 MCP 之间选择,优先使用 KooCLI;选定后,始终使用该方式
  3. 分页查询:所有工具调用统一使用 limit=200 分页,直到返回数量 < 200,然后合并所有分页数据。例外:cpu_io_diagnose_detail 使用 limit=800 分页(因数据量最大),直到返回数量 < 800,然后合并所有分页数据
  4. 报告时间:所有时间戳都必须转换为北京时间(UTC+8)。可使用 python -c "from datetime import datetime,timezone,timedelta; print(datetime.fromtimestamp({ms}/1000,tz=timezone(timedelta(hours=8))).strftime('%Y-%m-%d %H:%M:%S'))"
  5. SQL 显示:I/O 相关的异常查询最多显示 1024 个字符的具体 SQL;超过时截断并添加 "...";diagnosis_summary 中的 SQL 摘要最多 50 个字符
  6. I/O 阈值判断:I/O 阈值基于 RAID 组规格;iostat 中的每个 sdX 设备都对应一个 RAID 组;阈值已经是 RAID 组的整体性能规格,应直接比较,无需乘以磁盘数量
  7. 吞吐量和 IOPS 独立判断:两者可能同时过载;必须分别判断。吞吐量未过载但 IOPS 过载 → 仅 IOPS 过载,不属于双重过载
  8. 异常特征:吞吐量和 IOPS 偶尔达到最大值,但等待时间持续偏高 → 优先判断为 I/O 异常,而非过载

参考资料

文档说明
CLI 安装指南KooCLI 的安装和配置
MCP 安装指南DWS Autopilot MCP Server 的安装和配置
IAM 策略所需权限和策略 JSON
指标参考指标键字段和查询差异
I/O 背景知识RAID 架构、I/O 阈值、场景特征和重要原则
输出格式HTML 模板和填写规则
diagnosis_json 格式diagnosis_json 数据结构、content 字段格式规则、Ruby 用户约束
I/O 诊断参考场景路由表、调查方向和输出示例

说明

  • 安全性:切勿在对话或命令中暴露 AK/SK 值;切勿要求用户直接在对话中输入 AK/SK
  • 时间协议:from_ts/to_ts 必须使用毫秒时间戳;报告显示北京时间;将北京时间转换为时间戳时,必须追加 +08:00 时区后缀;切勿在脑中计算时间戳值;切勿将已有的毫秒时间戳转换为时间字符串后再转回
  • 输出限制:严格按照“输出格式”部分的模板输出诊断报告;不得修改模板结构、遗漏任何部分、添加修复建议、输出 SQL 优化语句、使用表情符号或自定义格式标签
  • 数据真实性:所有诊断结论都必须来自工具的实际返回结果;工具返回为空或调用失败时,标记为“无法获取”;禁止编造值
  • 已知限制:hcloud 不支持 --order_by 和 --sort_by 参数;查询后在本地按 ctime 降序排序;cpu_io_diagnose_detail 不支持按 host_id 过滤;查询整个集群后在本地过滤;cpu_io_diagnose_detail 返回平铺的行结构(每行一条查询),而非嵌套的 active_queries 数组;iostat 无法精确区分顺序 I/O 与随机 I/O 的比例;iostat 中的每个 sdX 设备对应一个 RAID 组,规格是 RAID 组的整体性能指标;io_data_available=false 属于正常情况(除非部署了 pidstat 采集插件,否则 io_read/io_write 均为 0),只有在 io_data_available=true 时,TopN 排序才有意义
  • RAID 架构:系统盘:2 块盘组成 RAID1(镜像),规格已是 RAID 组的整体性能指标;数据盘:4-6 块盘组成 RAID5(奇偶校验),规格已是 RAID 组的整体性能指标;DWS 按磁盘分布数据:数据倾斜只会导致单块磁盘过载,不会导致所有磁盘同时过载

评论

支持 Markdown