TiDB 集群故障排查实战:从监控告警到根因定位的完整思路

作为一名长期与数据库打交道的 DBA,我在接触 TiDB 分布式数据库的过程中,逐渐积累了一些故障排查的经验和方法论。与传统的单机数据库(如 MySQL、Oracle)不同,TiDB 的分布式架构带来了新的挑战——一个慢查询可能涉及 TiDB Server、PD、TiKV 甚至网络层的多个环节。

本文整理了一套从 监控告警 → 初步定位 → 深入分析 → 根因确认 的故障排查思路,希望对正在学习 TiDB 运维的同学有所帮助。

一、建立排查框架:分层定位法

TiDB 的核心架构分为三层,排查时我习惯按以下顺序逐层排除:

┌─────────────────────────────────────────┐
│  Layer 1: TiDB Server (SQL 层)          │
│  → 慢查询、执行计划、连接数、内存       │
├─────────────────────────────────────────┤
│  Layer 2: PD (调度层)                   │
│  → Region 分布、调度策略、TSO 分配      │
├─────────────────────────────────────────┤
│  Layer 3: TiKV (存储层)                 │
│  → RocksDB、Raft、Coprocessor、磁盘 IO │
└─────────────────────────────────────────┘

为什么要从上往下查? 因为 80% 的问题最终表现都在 SQL 层(慢查询、报错),但根因可能在下面任意一层。从现象倒推,逐层深入,避免盲目操作。

二、第一层:TiDB Server 快速诊断

2.1 慢查询分析

当收到"数据库慢了"的反馈,第一步永远是查慢查询日志:

sql

复制

-- 查看最近的慢查询(按耗时排序)
SELECT 
    Time, 
    Query_time, 
    DB, 
    LEFT(Query, 200) AS query_preview,
    Digest
FROM information_schema.slow_query
WHERE Time > DATE_SUB(NOW(), INTERVAL 1 HOUR)
ORDER BY Query_time DESC 
LIMIT 20;

关键指标:

  • Query_time > 1s:需要关注
  • Process_time vs Wait_time:处理时间大 = SQL 本身复杂;等待时间大 = 资源争抢
  • Cop_process vs Cop_wait:Coprocessor 耗时占比,判断瓶颈在 TiDB 还是 TiKV

2.2 查看当前运行的 SQL

sql

复制

-- 正在执行的查询及其状态
SELECT 
    id, 
    user, 
    db, 
    command, 
    time AS running_seconds,
    state, 
    LEFT(info, 200) AS current_query
FROM information_schema.processlist
WHERE command != 'Sleep'
ORDER BY time DESC;

state 字段非常有用:

  • autocommit / fetching rows:正常
  • Sending data:数据量大或网络慢
  • Waiting for ...:等待锁或资源
  • coprocessor:正在 TiKV 侧处理

2.3 执行计划分析

sql

复制

-- 分析慢 SQL 的执行计划
EXPLAIN ANALYZE 
SELECT ... 
FROM ... 
WHERE ...;

重点关注:

  • cop_task 是否过多(说明下推到 TiKV 的任务多)
  • TableFullScan / IndexFullScan:全表扫描,必须加索引
  • HashJoin_* vs IndexJoin_*:大表 Join 用 HashJoin 更高效
  • estRows vs actRows:估算行数与实际行数差距大,说明统计信息过期

sql

复制

-- 统计信息检查
SHOW STATS_HEALTHY;
-- 低于 80 的表需要重新收集
ANALYZE TABLE table_name;

三、第二层:PD 调度诊断

PD 是整个集群的"大脑"。很多性能问题表面看是 SQL 慢,根因却是 PD 调度异常。

3.1 检查 Region 健康度

bash

复制

# 使用 pd-ctl 工具
pd-ctl -u http://pd-server:2379

# 查看 store 状态
>> store
# 关注:region_count 是否均衡、leader_count 是否倾斜

# 检查 Region 分布
>> region --jq=".regions | group_by(.peers[0].store_id) | ..."

# 查看热点 Region
>> hot read    # 读热点
>> hot write   # 写热点

3.2 调度状态检查

sql

复制

-- 查看 PD 调度器配置
SHOW CONFIG WHERE type = 'pd' AND name LIKE '%schedule%';

关键配置:

  • leader-schedule-limit:Leader 调度并发(默认 4)
  • region-schedule-limit:Region 调度并发(默认 2048)
  • hot-region-schedule-limit:热点调度并发(默认 4)

调度的常见问题:

现象 可能原因 排查方向
Region 数量极度不均衡 调度被禁用或限制 检查 region-schedule-limit
Leader 集中在少数 Store Leader 调度策略异常 检查 leader-schedule-limit 和 Store 权重
热点无法打散 热点调度器未启用 检查 Split Region 策略
大量 Region 处于 pending 状态 PD leader 切换或 Store 异常 检查 PD 集群健康状态

3.3 TSO 延迟监控

TSO 是 TiDB 分布式事务的时间戳服务,TSO 慢会导致全局变慢:

sql

复制

-- 查看 TiDB 侧的 TSO 等待时间
-- 在 Grafana 监控中查看:TiDB → PD Client → PD TSO RPC Duration
-- P99 > 100ms 需要关注

bash

复制

# pd-ctl 查看 TSO 分配情况
>> tso

四、第三层:TiKV 深度排查

TiKV 是数据的最终存储层。到这层排查时,通常已经定位到具体 Region 或 Store 有问题。

4.1 RocksDB 相关

RocksDB 的 write stall 是 TiKV 最常见的性能杀手:

bash

复制

# 查看 Store 详细信息
tikv-ctl --host tikv-server:20160 raft-store --dump

# 检查 RocksDB 指标(Grafana)
# TiKV-Details → RocksDB-kv → Write Stall Duration Max
# 如果经常 > 0,说明写入压力大或 Compaction 跟不上

write stall 的常见原因和解决方案:

  1. memtable 满了
  • 现象:写入突然变慢,Grafana 显示 Write Stall
  • 解决:增大 write-buffer-size 或提高 max-write-buffer-number
  1. Level 0 文件数过多
  • 现象:Compaction 跟不上写入速度
  • 解决:调整 level0-slowdown-writes-triggerlevel0-stop-writes-trigger
  1. Pending Compaction Bytes 过大
  • 现象:磁盘 IO 打满
  • 解决:检查磁盘性能,考虑扩容或使用性能更好的磁盘

4.2 Raft 相关

bash

复制

# 查看 Region 的 Raft 状态
pd-ctl -u http://pd-server:2379 region <region-id>

# 查看 peer 状态
pd-ctl -u http://pd-server:2379 region sibling <region-id>

Raft 常见问题:

  • Leader 频繁切换:检查网络延迟、磁盘 IO
  • Raft Log 堆积:Follower 落后太多,可能需要快照同步
  • Region 无法选出 Leader:多数副本异常,需要紧急处理

4.3 Coprocessor 执行慢

Coprocessor 是 TiKV 侧的计算引擎。当 SQL 的 cop 任务耗时长:

sql

复制

-- 查看 Coprocessor 慢请求(需开启慢日志)
-- 关注 TiDB 日志中的 cop_backoff 信息
-- 常见 backoff 类型:
--   txnLock:事务锁冲突
--   regionMiss:Region 分裂/合并期间
--   tikvRPC:TiKV 响应慢
--   pdRPC:PD 响应慢

五、实战案例:一次"数据库突然变慢"的完整排查

5.1 现象

用户反馈:下午 3 点左右,业务写入突然变慢,P99 从 50ms 飙升到 5s。

5.2 排查过程

Step 1:检查慢查询

sql

复制

SELECT Time, Query_time, LEFT(Query, 200)
FROM information_schema.slow_query
WHERE Time BETWEEN '2024-06-01 14:50:00' AND '2024-06-01 15:10:00'
ORDER BY Query_time DESC LIMIT 10;

发现 80% 的慢查询都是简单的 INSERT 语句,但 Cop_wait 很高。

Step 2:检查存储层

进入 Grafana,定位到对应 TiKV 节点:

  • RocksDB Write Stall Duration 持续 > 0
  • Pending Compaction Bytes 高达 200GB+

Step 3:确认根因

原来是一小时前有一个离线数据导入任务,短时间内写入了大量数据,导致 Compaction 积压。

5.3 解决措施

  1. 短期:暂停导入任务,让 Compaction 自然消化积压数据
  2. 中期:调整 RocksDB 参数,增加 Compaction 线程
  3. 长期:大表导入采用分批策略,避免对在线业务造成影响

六、排查工具速查表

工具 用途 常用命令
pd-ctl PD 集群管理 store, region, hot, config show
tikv-ctl TiKV 节点调试 raft-store --dump, size, compact
tidb-ctl TiDB 管理 schema, region
Grafana 监控大盘 TiDB / PD / TiKV-Details
慢查询日志 SQL 分析 information_schema.slow_query
TiDB Dashboard 可视化诊断 SQL 分析、流量可视化、日志搜索

写在最后

分布式数据库的运维本质上考验的是 分层排查能力对系统架构的理解深度。TiDB 的模块化设计让排查有了清晰的路径,但真正决定效率的,还是排查者是否建立了正确的排查框架。

以下是个人总结的排查心法:

  1. 现象驱动,不要猜测 — 先看监控和日志,不要凭经验盲改
  2. 逐层排查,不要跳层 — 80% 的问题不需要动到 TiKV
  3. 改之前先备份配置 — 用 SHOW CONFIG 或者 pd-ctl 导出当前配置
  4. 一次只改一个变量 — 参数调优切忌多变量同时调整
  5. 保持学习 — TiDB 社区(AskTUG)和官方文档是最好的学习资源

本文为个人学习与实践总结,欢迎在评论区交流讨论。如果你正在准备 TiDB 认证或者日常运维中遇到问题,也欢迎一起探讨!

作者注:本文参考了 TiDB 官方文档、AskTUG 社区讨论以及 305-TiDB 故障排除课程大纲。如有不足之处,恳请指正。

2 个赞

学习了。

生产环境用TiDB两年,整体稳定。做好监控和慢查询检查就行。

这里应该使用information_schema.cluster_slow_query

1 个赞

谢谢分享,非常详细,实用,已收藏。
第一层 TiDB Server(SQL 层,优先查)
第二层 PD(调度层)
第三层 TiKV(存储层)
分三层排查,提供了详细思路

学习啦,感谢分享

收藏,感谢分享

希望大佬继续整理其他30课程,想学需要积分兑换。再次感谢分享。

总结到位,已收藏,确实,数据库的 分层排查能力对系统架构的理解深度 在解决实际问题中,很实用

总结的不错

优化器采用Cascade风格的成本框架,rule-based和cost-based混合决策。

感谢分享