执行 KB Step A 和 Step B,先获取集群元数据和 tier 架构信息。KB Step A/B 已完成。现在获取集群元数据来确定 tier 和 parent_id。**KB Step A 结论:** 集群类型为 `dedicated`,`cluster_type_v2 = dedicated`,所有组件(TiDB、TiKV、PD、TiFlash、node)均使用 `cluster_id = 10518506906906971664` 进行 metrics 查询,无需 `parent_id`。 **KB Step B 结论:** 已读取 pitfall catalog: - `ic-001`:ANALYZE 不应作为 TopSQL/SlowQuery 中的主因;应先检查非 ANALYZE 语句的 CPU 占比 - `ic-002`:统计信息过期不应作为 P0,若存在 missing index 应优先 CREATE INDEX 现在执行时间转换并运行 `collect_evidence.py`。时间窗口:start=1773741600, end=1773760200。现在运行 collect_evidence.py(设置 900s 超时)。证据已完整收集。TopSQL 无数据,需要核查 TiDB CPU 高负荷的底层。现在进一步分析慢查询 decoded_plan,同时补充收集基线对比数据(前一天同时段)及 TiDB CPU 按实例时序的详细数据。关键证据已浮现:NTDML-Delete 峰值与 TiDB CPU 高峰具有强相关性。现在分析这个模式及其与 decoded_plan 的关联。统计关联极为显著:NTDML-Delete 峰值分钟内,所有4个 TiDB 节点的 CPU 均为正常分钟的 **2.7~3.0x**。现在深入分析 decoded_plan 以及 NTDML-Delete 的特征。现在完成 Node E 交叉验证并给出最终诊断输出。 --- ## 诊断报告:集群 10518506906906971664 — TiDB CPU 持续升高 --- ### Root Cause **周期性 NTDML-Delete 高频 burst(高开销低行效 DML)** 是 TiDB CPU 持续抬升的主因:每隔约 10 分钟出现一次 DELETE 语句洪峰(峰值达 3826/s,持续约 1~2 分钟),但 affected_rows 极低(峰值仅 0.097 行/stmt),说明绝大多数 DELETE 执行了全量索引/表扫描却未命中目标行,导致 TiDB CPU 在峰值分钟内飙升至正常水位的 **2.7~3.0x**,贯穿整个 5 小时窗口。 --- ### Key Evidence 1. **NTDML-Delete 与 TiDB CPU 强相关(全部4节点一致)** - NTDML-Delete 峰值分钟(>2000/s,共 43 分钟)内,db-tidb-0/1/2/5 的 CPU 平均分别为 **26.4 / 26.1 / 26.6 / 29.0 cores**;正常分钟(<200/s)仅 **8.7 / 8.8 / 9.3 / 10.9 cores**,倍率 **2.7~3.0x**(统计置信:4节点一致,n=43 vs n=217) - NTDML-Delete 均值 579/s,峰值 3826/s,burst 频率约 **每10分钟一次**,与 CPU 周期性尖峰完全对齐 2. **高开销低行效 DML 特征**(ic-001/ic-002 均不适用) - `affected_rows_rate`:峰值 **370.9/s** vs `statement_rate` 峰值 3826/s → **0.097 行/stmt**,大量 DELETE 扫描但未命中行 - 每次 burst 产生大量空扫索引/表的 coprocessor 压力,TiDB parser/executor 开销随 QPS 线性放大 3. **跨日基线对比确认抬升** - 事故日(03-17)db nodegroup 均值 **12.3~14.7 cores**,峰值 **39.65~47.73 cores**(利用率 62~75%,告警级别) - 前一日(03-16)同时段均值 **8.6~11.3 cores**,峰值 **15.3~26.6 cores**(利用率 ~25~42%,正常) - 同一节点 db-tidb-5:事故日均值 **14.7 cores**,基线日均值 **11.3 cores**(1.3x),peak 差距更显著:47.7 vs 26.6 4. **dh_active_receive_logs 慢查询放大 coprocessor 压力**(次要因子) - exec_count=2006,avg=4.14s,max=6.16s;`process_keys=9,999,776`,`total_keys=26,651,535` - IndexLookUp 实际返回 **1,368,469 行** vs 估算 1,000 行(**1368x 严重低估**);扫描 5,569,717 行 - 统计信息严重过期:`modify_count=872,236,304` >> `analyzed_count=83,810,713`(**10x divergence**) --- ### Causality > **NTDML-Delete burst 周期触发(每10min)** → 大量 0-行命中 DELETE 密集执行(3826/s)→ TiDB 端 parser/planner/executor CPU 瞬时暴增(~27 cores/节点)→ 与持续运行的 `dh_active_receive_logs` 大扫描慢查询叠加 → TiDB CPU 整体维持高位(62~75% quota,P99 延迟升至 101ms),业务侧感知多节点 CPU 持续升高 --- ### Ruled Out / Not Relevant 基础设施层干净(EBS throttle=0,disk IO=0);TiKV 整体 CPU 正常(max 50% quota);db-tikv-15 的 gRPC P99 spike(472ms 仅出现 1 次,13:35 UTC,瞬时抖动,与主因无关);Go GC 正常(GC duration rate=0.3% wall time);日志无 ERROR/FATAL;TopSQL 无数据(not enabled),ANALYZE 未在慢查询中主导 CPU,ic-001/ic-002 均不适用。 --- ### Severity **High** — TiDB CPU 利用率 62~75%(warning 级别),周期性峰值接近 75%,如 burst 增强或并发上升可能触发 CPU 饱和;慢查询 P99 101ms 尚可接受但已明显高于基线。 --- ### Recommendations **P0 — 排查并控制 NTDML-Delete burst 根源** 1. **定位发起方**:联系业务侧确认每 10 分钟触发一次 DELETE 的调度任务(批量清理任务/定时 Job)。检查 WHERE 条件是否有合适的索引支撑,或在大多数情况下目标行不存在(导致 0-row 扫描)。 2. **消灭空扫 DELETE**:若 DELETE 的 WHERE 条件匹配率极低(实测约 10%),在应用侧增加前置 SELECT COUNT/EXISTS 检查,或改为 batch DELETE with pagination,减少无效执行次数。 3. **补充支撑索引**:若 NTDML-Delete 的 WHERE 谓词缺乏覆盖索引,为高频 DELETE 语句的过滤列 `CREATE INDEX`,减少每次执行的扫描量。 **P1 — 修复 dh_active_receive_logs 慢查询(次要但持续叠压)** 4. **先执行 ANALYZE**(精确范围):统计信息 modify_count/analyzed_count **10x divergence**(872M vs 83M),须立即更新直方图: ```sql ANALYZE TABLE dh_app_6756.dh_active_receive_logs; ``` 执行后验证:`SHOW STATS_HEALTHY WHERE db_name='dh_app_6756' AND table_name='dh_active_receive_logs'` 应达到 healthy≥80。 5. **评估索引覆盖度**:当前 `idx_dh_active_acid_status_cate_uptime_site_cb` 命中后仍需扫描 5.57M 行,因 `usercurrency` 和 `site_code` 过滤未在索引前缀中。若 ANALYZE 后优化器仍选同一计划,考虑: - 新建含 `usercurrency, site_code` 的复合索引,或 - 通过 SQL Binding 固定访问路径: ```sql CREATE BINDING FOR SELECT ... FROM dh_active_receive_logs WHERE ... USING SELECT /*+ USE_INDEX(dh_active_receive_logs, <更优索引名>) */ ...; ``` 6. **开启 TopSQL**:建议在 Clinic/TiDB Dashboard 启用 TopSQL(`tidb_enable_top_sql = ON`),以便后续事件可以精确归因到 SQL digest 和 CPU 占比,弥补本次 TopSQL 无数据的分析缺口。