外观
TiDB 日志分析与故障排查
日志是 TiDB 集群故障排查的重要依据,通过分析日志可以快速定位问题根源。本文将介绍 TiDB 日志分析与故障排查的方法、工具和最佳实践。
TiDB 日志体系
1. 日志类型
TiDB 集群包含多种组件,每种组件都有自己的日志:
- TiDB 日志:记录 SQL 执行、事务处理、连接管理等信息
- TiKV 日志:记录 Raft 协议、存储引擎、网络通信等信息
- PD 日志:记录集群调度、元数据管理、Leader 选举等信息
- TiFlash 日志:记录列式存储、查询执行等信息
- 监控组件日志:包括 Prometheus、Grafana、Alertmanager 等组件的日志
2. 日志格式
TiDB 组件的日志格式基本一致,包含以下字段:
[2024/01/01 12:00:00.123 +08:00] [INFO] [component] [file.go:123] ["message"] [key1=value1] [key2=value2]- 时间戳:日志产生的时间
- 日志级别:INFO、WARN、ERROR、FATAL、PANIC 等
- 组件名称:产生日志的组件
- 文件名和行号:日志产生的位置
- 日志消息:日志的具体内容
- 键值对:附加的上下文信息
3. 日志级别
TiDB 日志支持以下级别(从低到高):
- DEBUG:详细的调试信息,仅用于开发和调试
- INFO:普通的信息日志,记录正常的系统运行状态
- WARN:警告信息,表示可能存在问题但不影响系统运行
- ERROR:错误信息,表示系统出现了问题但仍能运行
- FATAL:致命错误,表示系统无法继续运行
- PANIC:恐慌信息,表示系统发生了严重错误,会导致进程崩溃
日志收集与存储
1. 日志文件路径
默认情况下,TiDB 组件的日志文件存储在以下路径:
- TiDB 日志:
/tidb-deploy/tidb-4000/log/tidb.log - TiKV 日志:
/tidb-deploy/tikv-20160/log/tikv.log - PD 日志:
/tidb-deploy/pd-2379/log/pd.log - TiFlash 日志:
/tidb-deploy/tiflash-9000/log/tiflash.log
2. 日志收集工具
使用 TiUP 收集日志
bash
# 收集所有节点的日志
tiup cluster logs [cluster-name]
# 收集特定节点的日志
tiup cluster logs [cluster-name] -N [node-ip:port]
# 收集特定角色的日志
tiup cluster logs [cluster-name] -R tidb,tikv
# 实时查看日志
tiup cluster logs [cluster-name] -f
# 收集最近 N 分钟的日志
tiup cluster logs [cluster-name] --since 30m使用 ELK Stack 收集日志
可以使用 Elasticsearch + Logstash + Kibana (ELK Stack) 来集中收集和分析 TiDB 日志:
- 配置 Logstash 输入:
txt
input {
file {
path => ["/tidb-deploy/*/log/*.log"]
type => "tidb-log"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}- 配置 Logstash 过滤:
txt
filter {
if [type] == "tidb-log" {
grok {
match => {
"message" => \"\[%{TIMESTAMP_ISO8601:timestamp}\] \[%{LOGLEVEL:level}\] \[%{DATA:component}\] \[%{DATA:file}\.%{WORD:extension}:%{NUMBER:line}\] \[\"%{DATA:message}\"\]( \[%{DATA:key_value_pairs}\])*\"}
}
}
date {
match => ["timestamp", "yyyy/MM/dd HH:mm:ss.SSS Z"]
target => "@timestamp"
}
}
}- 配置 Logstash 输出:
txt
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "tidb-logs-%{+YYYY.MM.dd}"
}
}3. 日志存储策略
- 保留期限:根据业务需求设置日志保留期限,建议至少保留 7 天
- 日志轮转:配置日志轮转,避免单个日志文件过大
- 压缩存储:对旧日志进行压缩,节省存储空间
- 备份策略:定期备份重要日志,防止日志丢失
日志分析技巧
1. 日志过滤与搜索
使用 grep 搜索日志
bash
# 搜索包含 "error" 的日志
grep -i error /tidb-deploy/tidb-4000/log/tidb.log
# 搜索包含 "panic" 或 "fatal" 的日志
grep -E "panic|fatal" /tidb-deploy/tidb-4000/log/tidb.log
# 搜索特定时间范围的日志
grep "2024/01/01 12:00" /tidb-deploy/tidb-4000/log/tidb.log
# 统计错误日志数量
grep -i error /tidb-deploy/tidb-4000/log/tidb.log | wc -l
# 显示错误日志的上下文
grep -i error -A 5 -B 5 /tidb-deploy/tidb-4000/log/tidb.log使用 awk 分析日志
bash
# 统计不同日志级别的数量
awk '{print $3}' /tidb-deploy/tidb-4000/log/tidb.log | sort | uniq -c
# 提取特定字段
grep -i error /tidb-deploy/tidb-4000/log/tidb.log | awk '{print $1, $2, $6}'
# 按时间统计错误数量
grep -i error /tidb-deploy/tidb-4000/log/tidb.log | awk '{print $1, $2}' | uniq -c2. 关键日志分析
TiDB 关键日志
# 连接错误
[ERROR] [server.go:123] ["connection closed"] [remoteAddr="10.0.0.1:12345"] [error="EOF"]
# 事务冲突
[WARN] [session.go:456] ["transaction retry"] [txn="txn-123"] [retryCount=3] [error="Write conflict"]
# SQL 执行错误
[ERROR] [executor.go:789] ["execute statement failed"] [sql="SELECT * FROM non_existent_table"] [error="Table 'non_existent_table' doesn't exist"]
# 内存不足
[FATAL] [memory.go:321] ["out of memory"] [allocBytes=1073741824] [totalBytes=4294967296]TiKV 关键日志
# Raft 选举超时
[WARN] [raft.rs:456] ["raft election timeout"] [region_id=123] [peer_id=456] [term=789]
# 磁盘空间不足
[ERROR] [storage.rs:789] ["disk full"] [path="/tidb-data/tikv-20160/data"] [available=104857600] [required=1073741824]
# RocksDB 写入错误
[ERROR] [rocksdb.rs:123] ["rocksdb write error"] [error="IO error: No space left on device"]
# Region 分裂
[INFO] [region.rs:456] ["region split"] [region_id=123] [left_region_id=456] [right_region_id=789]PD 关键日志
# Leader 选举
[INFO] [leader.rs:123] ["new leader elected"] [leader_id=123] [term=456]
# 调度异常
[WARN] [scheduler.rs:456] ["schedule failed"] [region_id=789] [reason="insufficient replicas"]
# 热点 Region
[INFO] [hotspot.rs:789] ["hot region detected"] [region_id=123] [type="write"] [count=1000]
# 存储节点 offline
[ERROR] [store.rs:123] ["store offline"] [store_id=456] [reason="heartbeat timeout"]3. 日志分析工具
使用 tiup cluster diag 收集诊断信息
bash
# 收集集群诊断信息
tiup cluster diag [cluster-name]
# 收集特定节点的诊断信息
tiup cluster diag [cluster-name] -N [node-ip:port]
# 收集特定角色的诊断信息
tiup cluster diag [cluster-name] -R tidb,tikv使用 TiDB Dashboard 分析日志
TiDB Dashboard 提供了日志搜索和分析功能,可以通过浏览器访问:
- 登录 TiDB Dashboard(默认地址:http://[pd-host]:2379/dashboard)
- 点击左侧菜单中的 "日志搜索"
- 设置搜索条件(时间范围、组件、日志级别、关键词等)
- 查看搜索结果,分析日志内容
常见故障排查案例
1. TiDB 连接失败
问题描述
客户端无法连接到 TiDB 服务器,提示 "Connection refused" 或 "Timeout"
排查步骤
检查 TiDB 进程是否运行:
bashps aux | grep tidb-server systemctl status tidb-server检查 TiDB 监听端口:
bashnetstat -tuln | grep 4000 ss -tuln | grep 4000检查 TiDB 日志:
bashgrep -i error /tidb-deploy/tidb-4000/log/tidb.log检查防火墙规则:
bashiptables -L -n | grep 4000 firewall-cmd --list-ports检查网络连接:
bashping <tidb-host> nc -zv <tidb-host> 4000
解决方案
- 如果 TiDB 进程未运行,重启 TiDB 服务
- 如果监听端口不正确,修改 TiDB 配置文件中的
bind-address和port参数 - 如果防火墙阻止连接,开放相应端口
- 如果网络不通,检查网络配置和路由
2. 查询执行缓慢
问题描述
SQL 查询执行时间过长,影响业务性能
排查步骤
查看慢查询日志:
bashgrep -i slow /tidb-deploy/tidb-4000/log/tidb.log使用 EXPLAIN 分析执行计划:
sqlEXPLAIN SELECT * FROM table_name WHERE column = 'value'; EXPLAIN ANALYZE SELECT * FROM table_name WHERE column = 'value';查看 TiKV 热点:
bashtiup ctl pd -u http://[pd-host]:2379 hot read tiup ctl pd -u http://[pd-host]:2379 hot write检查 TiKV 性能指标:
- CPU 使用率
- 内存使用率
- 磁盘 I/O
- 网络流量
解决方案
- 优化 SQL 查询,添加合适的索引
- 调整 TiDB 配置参数,如
tidb_mem_quota_query - 优化表结构,如分区表、分表
- 调整 PD 调度策略,解决热点问题
- 增加 TiKV 节点,分担负载
3. 事务冲突
问题描述
事务执行失败,提示 "Write conflict" 或 "Transaction retry exceeded max retry count"
排查步骤
查看 TiDB 日志:
bashgrep -i conflict /tidb-deploy/tidb-4000/log/tidb.log分析事务模式:
- 乐观事务 vs 悲观事务
- 长事务 vs 短事务
检查并发度:
- 同时执行的事务数量
- 事务的冲突概率
解决方案
- 缩短事务执行时间
- 使用悲观事务模式
- 调整事务重试参数,如
tidb_retry_limit - 优化应用逻辑,减少事务冲突
- 增加 TiDB 节点,提高并发处理能力
4. TiKV 节点离线
问题描述
TiKV 节点被标记为离线,影响集群可用性
排查步骤
检查 TiKV 进程状态:
bashps aux | grep tikv-server systemctl status tikv-server查看 TiKV 日志:
bashgrep -i error /tidb-deploy/tikv-20160/log/tikv.log检查 PD 日志:
bashgrep -i offline /tidb-deploy/pd-2379/log/pd.log检查磁盘空间:
bashdf -h /tidb-data检查系统资源:
bashtop free -h iostat -x
解决方案
- 如果 TiKV 进程未运行,重启 TiKV 服务
- 如果磁盘空间不足,清理磁盘或扩容
- 如果系统资源不足,调整配置或扩容
- 如果是硬件故障,更换硬件
5. PD Leader 频繁切换
问题描述
PD Leader 频繁切换,影响集群稳定性
排查步骤
查看 PD 日志:
bashgrep -i leader /tidb-deploy/pd-2379/log/pd.log检查 PD 节点状态:
bashtiup ctl pd -u http://[pd-host]:2379 member检查网络延迟:
bashping <pd-host1> -c 10 ping <pd-host2> -c 10检查系统时间:
bashdate
解决方案
- 确保 PD 节点之间的网络延迟较低(< 10ms)
- 确保 PD 节点的系统时间同步
- 调整 PD 配置参数,如
election-timeout - 增加 PD 节点数量,提高集群稳定性
日志分析最佳实践
1. 建立日志分析体系
- 统一日志收集:集中收集所有组件的日志
- 标准化日志格式:确保日志格式一致,便于分析
- 自动化日志分析:使用 ELK Stack 等工具自动化日志分析
- 实时监控告警:配置日志告警规则,及时发现问题
2. 制定日志分析流程
- 确定问题范围:明确需要分析的组件和时间范围
- 收集相关日志:收集所有相关组件的日志
- 过滤和搜索:使用关键词和过滤条件缩小范围
- 分析日志内容:仔细阅读日志,理解问题上下文
- 定位问题根源:通过日志关联和分析,定位问题根源
- 制定解决方案:根据问题根源制定解决方案
- 验证解决方案:实施解决方案后,验证问题是否解决
3. 常见日志分析误区
- 只看错误日志:忽略 INFO 和 WARN 日志,可能错过重要线索
- 孤立分析单个日志:没有关联多个组件的日志,难以定位问题
- 忽略上下文信息:不考虑日志产生的上下文,可能误判问题
- 没有长期分析:只分析当前日志,不进行长期趋势分析
4. 日志分析工具推荐
- 命令行工具:grep、awk、sed、tail、head
- 日志管理平台:ELK Stack、Graylog、Loki
- 监控告警工具:Prometheus、Grafana、Alertmanager
- TiDB 专用工具:TiDB Dashboard、tiup cluster diag
常见问题(FAQ)
Q1: 如何调整 TiDB 日志级别?
A1: 可以通过以下方式调整 TiDB 日志级别:
修改配置文件:
toml[log] level = "info" # 可以设置为 debug、info、warn、error动态调整:
sqlSET GLOBAL tidb_log_level = 'info';命令行参数:
bashtiup cluster edit-config [cluster-name] # 修改 log.level 参数 tiup cluster reload [cluster-name] -R tidb
Q2: 如何查看 TiDB 慢查询日志?
A2: 可以通过以下方式查看 TiDB 慢查询日志:
直接查看日志文件:
bashgrep -i slow /tidb-deploy/tidb-4000/log/tidb.log使用 TiDB Dashboard:
- 登录 TiDB Dashboard
- 点击左侧菜单中的 "慢查询"
- 设置查询条件,查看慢查询日志
查询 mysql.slow_log 表:
sqlSELECT * FROM mysql.slow_log LIMIT 10;
Q3: 如何收集 TiDB 集群的诊断信息?
A3: 可以使用 tiup cluster diag 命令收集 TiDB 集群的诊断信息:
bash
# 收集所有节点的诊断信息
tiup cluster diag [cluster-name]
# 收集特定节点的诊断信息
tiup cluster diag [cluster-name] -N [node-ip:port]
# 收集特定角色的诊断信息
tiup cluster diag [cluster-name] -R tidb,tikvQ4: 如何分析 TiKV 磁盘 I/O 问题?
A4: 可以通过以下方式分析 TiKV 磁盘 I/O 问题:
查看 TiKV 日志:
bashgrep -i i/o /tidb-deploy/tikv-20160/log/tikv.log使用 iostat 命令:
bashiostat -x 1查看 RocksDB 统计信息:
bashtiup ctl tikv --host <tikv-host>:20160 rocksdb stats查看 TiKV 监控指标:
- disk_read_bytes_total
- disk_write_bytes_total
- disk_io_time_seconds_total
Q5: 如何防止日志文件过大?
A5: 可以通过以下方式防止日志文件过大:
配置日志轮转:
- 修改组件的日志配置,设置日志轮转规则
- 例如,每天轮转一次,保留 7 天的日志
调整日志级别:
- 在生产环境中,将日志级别设置为 info 或 warn
- 避免使用 debug 级别,减少日志量
使用日志压缩:
- 对旧日志进行压缩,节省存储空间
- 例如,使用 gzip 压缩旧日志
集中日志管理:
- 使用 ELK Stack 等工具集中管理日志
- 便于日志分析和存储管理
