关于 huawei-cloud-dws-cpu-diag
用于诊断 Huawei Cloud DWS 集群 CPU 使用率过高问题的技能,面向处理集群告警和负载异常的运维人员。它采集监控指标、分析可能原因,并生成标准化诊断报告。
主要功能
- 01采集集群 CPU 及相关指标
- 02分析节点负载和业务并发
- 03检查查询与进程 CPU 数据
- 04使用 KooCLI,必要时回退到 MCP
- 05生成标准化诊断报告
适用场景
- 01调查 DWS 集群 CPU 告警
- 02定位集群负载异常原因
- 03响应用户发起的 CPU 诊断请求
MCP 相关
技能可调用 dws_autopilot MCP 服务查询集群、主机和指标;当 KooCLI 不可用时将其作为替代方式。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ huaweicloud/ huaweicloud-skills --skill huawei-cloud-dws-cpu-diag安装后在 Claude Code 中输入/huawei-cloud-dws-cpu-diag确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/dws-mcp-installation-guide.mdiam-policies.mdmetric-reference.md详细介绍
华为云 DWS CPU 高使用率诊断技能
概述
此技能专用于 DWS 集群 CPU 高使用率的根因诊断。当集群触发 CPU 使用率过高告警时,它会自动收集指标数据、分析根因(客户侧/系统侧),并输出标准化诊断报告。
架构:KooCLI (hcloud) → DWS Autopilot API → 集群监控指标;MCP Server (dws_autopilot) → 同一 API 的备用通道
适用场景:
- DWS 集群 CPU 使用率过高告警
- CPU 负载异常调查
- 用户主动发起 CPU 诊断请求
典型用例:
- “我的 DWS 集群 CPU 使用率很高,帮我诊断一下”
- “收到 CPU 告警,集群 ID 是 xxx,帮我分析原因”
- “DWS 集群 CPU 满负荷了,看看是什么原因”
重要规则:所有诊断结论都必须来自工具的实际返回结果。禁止编造或假设数值。输出内容只能包含诊断报告;禁止添加修复建议、输出 SQL 优化语句或使用表情符号。
前置条件
1. CLI 要求
- KooCLI (hcloud) >= 3.2.0
- 验证安装:
hcloud version - 如果尚未安装或版本过低,请参阅 CLI 安装指南
2. MCP Server 配置(备用)
- KooCLI 不可用时,使用 MCP Server 作为替代方案
- 请参阅 MCP 安装指南
3. 身份验证配置
- 有效的华为云凭证(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_id | project_id |
| 集群 ID | --cluster_id | cluster_id |
| 指标名称 | --metric_name | metric_name |
| 开始时间 | --from | from_ts |
| 结束时间 | --to | to_ts |
| 分页偏移量 | --offset | offset |
| 分页限制 | --limit | limit |
| 排序字段 | (不支持) | order_by |
| 排序方向 | (不支持) | sort_by |
MCP 工具
| 工具名称 | 用途 |
|---|---|
dws_autopilot_get_clusters | 查询集群列表,获取集群名称、project_id 等信息。 |
dws_autopilot_get_hosts | 查询主机信息 |
dws_autopilot_get_metric | 查询指标数据 |
可用的 metric_name:CpuStat、business_concurrency、cpu_io_diagnose_detail、node_process_cpu_top20、command_cpu_usage
有关各指标的关键字段和各步骤的查询差异,请参阅指标参考。
分页规范
所有工具调用(MCP 和 hcloud)都必须使用分页查询,以防单次响应过大并超出令牌限制。
分页规则:
- 统一使用
limit=200(不要使用 800 或其他较大的值) - 第一页使用
offset=0;如果返回的数据条数 = 200,则令offset+=200并继续查询 - 重复查询,直到返回的数据条数 < 200,然后合并所有分页数据
- 合并时,将所有页面的数据数组拼接成完整数据集
MCP 调用示例(使用 CpuStat):
Page 1: dws_autopilot_get_metric(project_id, cluster_id, metric_name="CpuStat", 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="CpuStat", from_ts, to_ts, limit=200, offset=200)
If returned data length < 200: Stop pagination, merge page 1 + page 2 data
hcloud 调用示例(使用 CpuStat):
Page 1: hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<id> --metric_name=CpuStat --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=CpuStat --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:环境检测
执行 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:查询 CpuStat
调用指标查询,设置 metric_name="CpuStat",时间范围:from_ts=first_alarm_time - 1200000,to_ts=first_alarm_time。在 MCP 模式下,使用 limit=200 进行分页查询。
自动驾驶不可用的判定:project_id 为空,或返回 50201/RDS.9999 错误 → 跳过步骤 1-5.5,将所有指标标记为“不可用”,直接进入步骤 6。
解析:CPU 使用率 = usr + sys。按 host_id 分组,分别计算每个节点在时间窗口内的 CPU 使用率最大值和平均值。
TOP 节点筛选:按节点平均 CPU 使用率降序排序,选择 TOP 节点:
- 集群节点数 <= 6:选择所有节点
- 集群节点数 > 6:仅选择 TOP 3 个节点
节点范围分类:所有节点 CPU 均较高(高 CPU 节点比例 >= 80%)→ all_nodes;单个节点 CPU 较高 → single_node;部分节点 CPU 较高 → partial_nodes。
负载均衡判定:对于 TOP 节点,比较 CPU 最大值与平均值的差异。如果所有 TOP 节点均满足 |max - avg| / avg < 20%,则为“负载均衡”;后续步骤(步骤 4-5.5)仅需分析 TOP 3 个节点。否则为“负载不均衡”;后续步骤需分析所有高 CPU 节点。
输出:cpu_by_host、max_cpu_hosts(按平均值排序的 TOP 节点列表)、problem_host_id、problem_host_cpu_usage、cpu_scope、high_cpu_nodes、is_balanced、nodes_to_analyze(后续步骤要分析的节点列表)
步骤 2:获取主机名称
调用主机信息查询(MCP 模式下使用 limit=200 进行分页),构建 host_id → {host_name, ip} 映射表。仅查询步骤 1 输出的 nodes_to_analyze 中涉及的节点的主机信息。
输出:host_id_to_info_map、problem_host_ip、node_name
步骤 3:查询业务并发量
调用指标查询,设置 metric_name="business_concurrency"。在 MCP 模式下,使用 limit=200 进行分页查询,直到返回数量 < 200。
输出:max_concurrency、avg_concurrency、is_high_concurrency
步骤 4:查询 CPU 最高节点的诊断详情
调用指标查询,设置 metric_name="cpu_io_diagnose_detail"。不支持按 host_id 筛选;查询整个集群后,再根据步骤 1 输出的 nodes_to_analyze 进行筛选。MCP 模式必须使用 limit=200 进行分页查询(该指标的数据量最大,单页查询 800 条会超出 token 限制),直到返回数量 < 200,然后合并所有分页数据,再进行筛选。
解析:提取活跃查询、用户、持续时间和进程信息。ctime 是采集时间,而非 SQL 开始时间;当 duration_ms 存在时,SQL 开始时间 = ctime - duration_ms。仅统计 state=active 的用户。inst_name 包含 "cn" → CN 实例;包含 "dn" → DN 实例。
注意:cpu_io_diagnose_detail 返回的是扁平行结构(每行一条查询记录),而非嵌套的 active_queries 数组。关键字段:ctime、host_id、inst_name、username、cpu_rate、count、datname、io_read、io_write、query_id、query、duration_ms、state。
输出:single_statement_detected、single_statement_info、high_concurrency_detected、concurrent_stats、inst_type、high_freq_queries、heavy_queries
步骤 5:查询进程 CPU TOP 20
调用指标查询,设置 metric_name="node_process_cpu_top20"。在 MCP 模式下,使用 limit=200 进行分页查询。查询整个集群后,再根据步骤 1 输出的 nodes_to_analyze 进行筛选。注意:此指标可能返回 null;如果返回 null,则标记为“不可用”并跳过。
输出:processes_by_host、top_cpu_process
步骤 5.5:查询命令级 CPU 使用率
调用指标查询,设置 metric_name="command_cpu_usage"。在 MCP 模式下,使用 limit=200 进行分页查询。
数据结构:每行表示一台主机在一个采集时间的一个进程。关键字段:ctime、host_id、command、args(command_detail)、cpu_rate、username。command 字段用于区分进程类型:gaussdb-dn(数据节点主进程)、gaussdb-cn(协调节点主进程)、gaussdb(围栏 UDF 子进程)、python3、java、sh、cm_agent、gs_gtm 等。args 字段包含完整的命令详情(例如,/DWS/manager/app/bin/gaussdb --datanode ...)。username 字段是操作系统用户(例如,Ruby、root),不是数据库用户。
Gaussdb 主进程定义:command 字段为 gaussdb-dn 或 gaussdb-cn → gaussdb 主进程(其 CPU 使用率归因于 SQL 语句和根因,不计入 Top 3 进程)。command 字段为 gaussdb(围栏 UDF 主进程)→ 不是主进程,计入 Top 3 进程。
输出:command_by_host、abnormal_process
步骤 6:分析诊断结果
诊断优先级:先检查范围,再查找原因;优先考虑业务异常;配置和系统问题放在最后。
CPU 类型判定:SysCPU/UserCPU >= 1/2 → SysCPU 高;否则 → UserCPU 高。
用户身份判定:数据库用户(userName)为 omm/Ruby → 系统原因;否则 → 客户侧原因。
异常进程识别:command 包含 safest/AsiaInfo/aliyundun → 杀毒软件;command 不包含 gaussdb/postgres/gtm/cm_agent → 非 gaussdb 进程;command 为 gaussdb(围栏 UDF,不是 gaussdb-dn/gaussdb-cn)→ 子进程异常。
客户侧原因:高并发(多用户/单用户)、单条语句(CPU 占比 > 30%)、数据倾斜/计算倾斜。高并发和单条语句可能同时匹配。
系统原因:系统内部 SQL(VACUUM 等)、异常进程、SysCPU 高。
统计信息:计算以下三类 Top 3:
- Top 3 语句(来自 cpu_io_diagnose_detail):按 cpu_rate 降序排列(cpu_rate 已是实例级百分比,直接使用),输出 query_id、username、开始时间、CPU 占比、具体 SQL(最多 1024 个字符)。每行代表一个实例上的一条查询;不要通过除以全局总量重新计算占比。
- Top 3 数据库用户(来自 cpu_io_diagnose_detail):按 username 汇总 cpu_rate(仅统计 state=active),输出 username 和占比。此处的 username 是数据库用户,不是操作系统用户。占比 = 用户 cpu_rate 总和 / 所有用户 cpu_rate 总和 × 100%。
- Top 3 操作系统进程(来自 command_cpu_usage):按 command 汇总 cpu_rate,排除 gaussdb 主进程(command 为
gaussdb-dn或gaussdb-cn);其余进程按 cpu_rate 降序排列,取 Top 3。注意:gaussdb(围栏 UDF)不是主进程,应计入统计。command_cpu_usage 中的 username 字段是操作系统用户,与数据库用户不同;不要混淆。占比 = 进程 cpu_rate 总和 / 所有非主进程 cpu_rate 总和 × 100%。
步骤 7:生成诊断报告
按照“输出格式”部分中的模板生成 HTML 报告。生成报告后,将 HTML 文件保存到当前工作目录(工作区根文件夹),文件名为 dws_cpu_diagnosis_report_{timestamp}.html,其中 {timestamp} 为当前机器本地时间,格式为 yyyyMMdd_HHmmss(例如,dws_cpu_diagnosis_report_20260623_150421.html)。
核心命令
查询集群列表
# 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 |
| project_id | 必填 | 项目 ID | N/A |
| cluster_id | 必填 | 集群 ID | N/A |
| first_alarm_time | 必填 | 首次告警时间(毫秒时间戳) | N/A |
| alarm_name | 必填 | 告警名称 | N/A |
| region_id | 可选 | 区域标识符 | N/A |
| node_name | 可选 | 告警节点名称 | 空(集群级告警) |
| cluster_name | 可选 | 集群名称 | 使用 cluster_id |
| alarm_severity | 可选 | 告警严重程度 | N/A |
输出格式
注意:严格按照以下模板输出并返回。不要分析或总结模板内容,不要省略任何部分,也不要修改模板结构。输出必须与模板一致。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
body { font-family: "Microsoft YaHei", "PingFang SC", sans-serif; margin: 20px; background: #f5f7fa; color: #1d2129; }
.report { max-width: 960px; margin: 0 auto; background: #fff; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); overflow: hidden; }
.header { background: linear-gradient(135deg, #165dff, #0fc6c2); color: #fff; padding: 24px 32px; }
.header h1 { margin: 0; font-size: 22px; letter-spacing: 1px; }
.header .subtitle { margin-top: 4px; font-size: 13px; opacity: 0.85; }
.section { padding: 20px 32px; border-bottom: 1px solid #e5e6eb; }
.section:last-child { border-bottom: none; }
.section-title { font-size: 16px; font-weight: 600; color: #165dff; margin: 0 0 12px 0; padding-left: 10px; border-left: 3px solid #165dff; }
.info-grid { display: grid; grid-template-columns: 120px 1fr; row-gap: 8px; }
.info-key { color: #86909c; font-size: 14px; text-align: right; padding-right: 12px; }
.info-val { color: #1d2129; font-size: 14px; font-weight: 500; word-break: break-all; }
.conclusion-item { padding: 8px 12px; margin-bottom: 6px; background: #fff7e8; border-left: 3px solid #ff7d00; border-radius: 0 4px 4px 0; font-size: 14px; }
.conclusion-item.normal { background: #e8ffea; border-left-color: #00b42a; }
.locate-block { margin: 6px 0 6px 16px; padding: 10px 14px; background: #f7f8fa; border-radius: 4px; font-size: 13px; }
.locate-block .loc-row { display: flex; margin-bottom: 4px; }
.locate-block .loc-key { width: 80px; color: #86909c; flex-shrink: 0; }
.locate-block .loc-val { color: #1d2129; word-break: break-all; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th { background: #f2f3f5; color: #4e5969; font-weight: 600; text-align: left; padding: 10px 12px; border-bottom: 2px solid #e5e6eb; }
td { padding: 10px 12px; border-bottom: 1px solid #f2f3f5; vertical-align: top; }
tr:hover td { background: #f7f8fa; }
.sql-text { font-family: "Cascadia Code", "Fira Code", "Consolas", monospace; font-size: 12px; color: #4e5969; max-width: 500px; word-break: break-all; white-space: pre-wrap; }
.pct-bar { display: inline-block; height: 16px; border-radius: 2px; background: linear-gradient(90deg, #165dff, #0fc6c2); vertical-align: middle; }
.pct-val { margin-left: 6px; font-weight: 600; color: #165dff; }
.tag { display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 12px; font-weight: 500; }
.tag-warn { background: #fff7e8; color: #ff7d00; }
.tag-danger { background: #ffece8; color: #cb2634; }
.tag-info { background: #e8f3ff; color: #165dff; }
</style>
</head>
<body>
<div class="report">
<div class="header">
<h1>DWS 集群 CPU 诊断报告</h1>
<div class="subtitle">{region_id} | {resource_name}</div>
</div>
<div class="section">
<div class="section-title">基本信息</div>
<div class="info-grid">
<span class="info-key">所属服务</span><span class="info-val">DWS</span>
<span class="info-key">所属区域</span><span class="info-val">{region_id}</span>
<span class="info-key">集群名称</span><span class="info-val">{resource_name}</span>
<span class="info-key">集群ID</span><span class="info-val">{resource_id}</span>
<span class="info-key">TOP节点</span><span class="info-val">{node_name}</span>
</div>
</div>
<div class="section">
<div class="section-title">诊断结论</div>
{diagnosis_summary}
</div>
<div class="section">
<div class="section-title">CPU贡献 Top3 语句</div>
<table>
<tr><th style="width:40px">#</th><th style="width:180px">QueryID</th><th style="width:80px">用户</th><th style="width:80px">CPU占比</th><th style="width:160px">时间</th><th>SQL</th></tr>
<tr><td>1</td><td>{query_id}</td><td>{username}</td><td>{pct}%</td><td>{start_time_beijing}</td><td class="sql-text">{query_text}</td></tr>
<tr><td>2</td><td>{query_id}</td><td>{username}</td><td>{pct}%</td><td>{start_time_beijing}</td><td class="sql-text">{query_text}</td></tr>
<tr><td>3</td><td>{query_id}</td><td>{username}</td><td>{pct}%</td><td>{start_time_beijing}</td><td class="sql-text">{query_text}</td></tr>
</table>
</div>
<div class="section">
<div class="section-title">CPU贡献 Top3 用户</div>
<table>
<tr><th style="width:40px">#</th><th>用户名</th><th style="width:260px">CPU占比</th></tr>
<tr><td>1</td><td>{user1}</td><td><span class="pct-bar" style="width:{bar1}px"></span><span class="pct-val">{pct1}%</span></td></tr>
<tr><td>2</td><td>{user2}</td><td><span class="pct-bar" style="width:{bar2}px"></span><span class="pct-val">{pct2}%</span></td></tr>
<tr><td>3</td><td>{user3}</td><td><span class="pct-bar" style="width:{bar3}px"></span><span class="pct-val">{pct3}%</span></td></tr>
</table>
</div>
<div class="section">
<div class="section-title">CPU贡献 Top3 进程(不含gaussdb主进程)</div>
<table>
<tr><th style="width:40px">#</th><th>进程名</th><th style="width:260px">CPU占比</th></tr>
<tr><td>1</td><td>{process1}</td><td><span class="pct-bar" style="width:{bar1}px"></span><span class="pct-val">{pct1}%</span></td></tr>
<tr><td>2</td><td>{process2}</td><td><span class="pct-bar" style="width:{bar2}px"></span><span class="pct-val">{pct2}%</span></td></tr>
<tr><td>3</td><td>{process3}</td><td><span class="pct-bar" style="width:{bar3}px"></span><span class="pct-val">{pct3}%</span></td></tr>
</table>
</div>
</div>
</body>
</html>
diagnosis_summary 填写规则:
- 如果所有指标均正常 → 输出
<div class="conclusion-item normal">诊断暂未发现异常</div> - 否则,每个异常输出一个
<div class="conclusion-item">,内容格式为:<anomaly_type>: <factual_description> - 如果确定了具体 SQL,在异常项 div 后追加一个位置子块:
<div class="conclusion-item"><anomaly_type>: <factual_description></div> <div class="locate-block"> <div class="loc-row"><span class="loc-key">SQL摘要</span><span class="loc-val">{specific_sql} (max 50 characters)</span></div> <div class="loc-row"><span class="loc-key">QueryID</span><span class="loc-val">{query_id}</span></div> <div class="loc-row"><span class="loc-key">用户名</span><span class="loc-val">{username}</span></div> <div class="loc-row"><span class="loc-key">启动时间</span><span class="loc-val">{start_time_beijing}</span></div> </div> - 高并发和单条语句可以作为独立异常项同时出现
- 异常项可使用标签提升可读性:系统原因使用
<span class="tag tag-warn">系统</span>,客户端原因使用<span class="tag tag-danger">客户侧</span>,高并发使用<span class="tag tag-info">高并发</span>
Top 3 语句填写规则:
- 数据来源:cpu_io_diagnose_detail 中按 cpu_rate 降序排列的前 3 条语句
- cpu_rate 已是实例级百分比(例如,76.5% 表示此查询在该实例上使用了 76.5% 的 CPU)。直接使用 cpu_rate 值作为 CPU 占比;不要除以全局总量或节点总量重新计算
- cpu_io_diagnose_detail 中的每一行代表一个实例上的一次查询执行;排序选取前 3 条时,每行应独立处理
- QueryID:取自 query_id 字段;多条相似 SQL 以逗号分隔,并附带数量标注(例如,“73183494456652581等4条”)
- Username:取自 username 字段
- 时间:存在 duration_ms 时,使用 ctime - duration_ms 换算为北京时间,列标题显示“启动时间”;不存在 duration_ms 时,使用 ctime 换算为北京时间,列标题显示“采集时间”
- CPU 占比:直接使用 cpu_rate 字段值(已是百分比),保留 1 位小数(例如,76.5%)
- SQL:取自 query 字段,最多显示 1024 个字符;超出时以 "..." 截断
- gaussdb 主进程不作为独立语句列出;其 CPU 开销合并到对应的根因描述中
- 如果没有语句数据(例如,cpu_io_diagnose_detail 为空),则在表格中填写“无法获取”
Top 3 用户填写规则:
- 数据来源:按 username 聚合 cpu_io_diagnose_detail 中的 cpu_rate
- 此处的 username 是数据库用户,不是 OS 用户。不要使用 command_cpu_usage 中的 username 字段
- 只统计 state=active 的数据库用户
- 占比 = 用户的 cpu_rate 总和 / 所有用户的 cpu_rate 总和 × 100%
- 如果数据点少于 3 个,则列出实际数量
- pct-bar 宽度计算:
width = Math.round(ratio / max_ratio * 200),其中 max_ratio 是排名第一的用户占比 Top 3 进程填充规则: - 数据来源:从
command_cpu_usage中按命令聚合的 cpu_rate command_cpu_usage中的 username 字段表示 OS 用户,与cpu_io_diagnose_detail中的数据库用户不同;不要混淆两者- 排除 Gaussdb 主进程:排除
command为gaussdb-dn或gaussdb-cn的行(它们的 CPU 使用率归入 SQL 语句和根因)。不要排除gaussdb(fenced UDF 主进程)——它是子进程,应纳入 Top 3 - 将其余进程按 cpu_rate 降序排列,取 Top 3
- 占比 = 进程的 cpu_rate 总和 / 所有非主进程的 cpu_rate 总和 × 100%
- 进程显示名称:直接使用
command字段值(例如gaussdb、python3、java、sh、cm_agent、gs_gtm)。同一 command 下的多个条目即使args不同,也会聚合到同一个命令名称下 - 如果 node_process_cpu_top20 返回 null,且 command_cpu_usage 也为空,则在表格中填入“无法获取”
- pct-bar 宽度的计算方式与 Top 3 用户相同
通用填充规则:集群名称优先使用 cluster_name;如果为空,则使用 cluster_id;node_name 为空时,填入“集群级告警”;Gaussdb 主进程(command 为 gaussdb-dn 或 gaussdb-cn)的 CPU 使用率合并到相应的根因描述中;Gaussdb fenced UDF(command 为 gaussdb)不是主进程,应出现在 Top 3 进程中;多条相似 SQL 描述为“N条同类xxx查询”;所有时间均使用北京时间;超过 50 个字符的语句摘要截断并添加 "...";输出为可直接在浏览器中呈现的完整 HTML 文档;SQL 文本中的 < > & 必须转义为 < > &。
最佳实践
- 时间戳处理:first_alarm_time 已经是毫秒时间戳;直接将其用于工具参数。不要先转换为时间字符串,再转换回时间戳(以避免 8 小时偏差)
- 工具选择:在 KooCLI 和 MCP 之间选择,优先使用 KooCLI;一旦选定,就始终使用该方法
- 分页查询:所有工具调用统一使用 limit=200 分页,直到返回数量 < 200,然后合并所有分页数据。cpu_io_diagnose_detail 的数据量最大;必须分页
- 报告时间:所有时间戳都必须转换为北京时间(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'))" - SQL 显示:Top 3 语句最多显示 1024 个字符的具体 SQL;超出时截断并添加 "...";diagnosis_summary 中的 SQL 摘要最多 50 个字符
- 节点筛选优化:在步骤 1 解析 CpuStat 时,分别计算每个节点的 CPU 使用率最大值和平均值;当集群节点数 > 6 时,仅关注 TOP 3 节点;如果 TOP 节点的最大值与平均值之差 < 20%,则后续步骤仅分析 TOP 3,否则分析所有高 CPU 节点
参考资料
| 文档 | 描述 |
|---|---|
| CLI 安装指南 | KooCLI 安装和配置 |
| MCP 安装指南 | DWS Autopilot MCP Server 安装和配置 |
| IAM 策略 | 所需权限和策略 JSON |
| 指标参考 | 指标键字段和查询差异 |
注意事项
- 安全性:绝不要在对话或命令中暴露 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 数组;node_process_cpu_top20 可能返回 null;command_cpu_usage 的
command字段用于区分gaussdb-dn/gaussdb-cn(主进程,排除在 Top 3 之外)和gaussdb(隔离的 UDF,纳入统计)