Skip to content

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 日志:

  1. 配置 Logstash 输入
txt
input {
  file {
    path => ["/tidb-deploy/*/log/*.log"]
    type => "tidb-log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}
  1. 配置 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"
    }
  }
}
  1. 配置 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 -c

2. 关键日志分析

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 提供了日志搜索和分析功能,可以通过浏览器访问:

  1. 登录 TiDB Dashboard(默认地址:http://[pd-host]:2379/dashboard)
  2. 点击左侧菜单中的 "日志搜索"
  3. 设置搜索条件(时间范围、组件、日志级别、关键词等)
  4. 查看搜索结果,分析日志内容

常见故障排查案例

1. TiDB 连接失败

问题描述

客户端无法连接到 TiDB 服务器,提示 "Connection refused" 或 "Timeout"

排查步骤

  1. 检查 TiDB 进程是否运行

    bash
    ps aux | grep tidb-server
    systemctl status tidb-server
  2. 检查 TiDB 监听端口

    bash
    netstat -tuln | grep 4000
    ss -tuln | grep 4000
  3. 检查 TiDB 日志

    bash
    grep -i error /tidb-deploy/tidb-4000/log/tidb.log
  4. 检查防火墙规则

    bash
    iptables -L -n | grep 4000
    firewall-cmd --list-ports
  5. 检查网络连接

    bash
    ping <tidb-host>
    nc -zv <tidb-host> 4000

解决方案

  • 如果 TiDB 进程未运行,重启 TiDB 服务
  • 如果监听端口不正确,修改 TiDB 配置文件中的 bind-addressport 参数
  • 如果防火墙阻止连接,开放相应端口
  • 如果网络不通,检查网络配置和路由

2. 查询执行缓慢

问题描述

SQL 查询执行时间过长,影响业务性能

排查步骤

  1. 查看慢查询日志

    bash
    grep -i slow /tidb-deploy/tidb-4000/log/tidb.log
  2. 使用 EXPLAIN 分析执行计划

    sql
    EXPLAIN SELECT * FROM table_name WHERE column = 'value';
    EXPLAIN ANALYZE SELECT * FROM table_name WHERE column = 'value';
  3. 查看 TiKV 热点

    bash
    tiup ctl pd -u http://[pd-host]:2379 hot read
    tiup ctl pd -u http://[pd-host]:2379 hot write
  4. 检查 TiKV 性能指标

    • CPU 使用率
    • 内存使用率
    • 磁盘 I/O
    • 网络流量

解决方案

  • 优化 SQL 查询,添加合适的索引
  • 调整 TiDB 配置参数,如 tidb_mem_quota_query
  • 优化表结构,如分区表、分表
  • 调整 PD 调度策略,解决热点问题
  • 增加 TiKV 节点,分担负载

3. 事务冲突

问题描述

事务执行失败,提示 "Write conflict" 或 "Transaction retry exceeded max retry count"

排查步骤

  1. 查看 TiDB 日志

    bash
    grep -i conflict /tidb-deploy/tidb-4000/log/tidb.log
  2. 分析事务模式

    • 乐观事务 vs 悲观事务
    • 长事务 vs 短事务
  3. 检查并发度

    • 同时执行的事务数量
    • 事务的冲突概率

解决方案

  • 缩短事务执行时间
  • 使用悲观事务模式
  • 调整事务重试参数,如 tidb_retry_limit
  • 优化应用逻辑,减少事务冲突
  • 增加 TiDB 节点,提高并发处理能力

4. TiKV 节点离线

问题描述

TiKV 节点被标记为离线,影响集群可用性

排查步骤

  1. 检查 TiKV 进程状态

    bash
    ps aux | grep tikv-server
    systemctl status tikv-server
  2. 查看 TiKV 日志

    bash
    grep -i error /tidb-deploy/tikv-20160/log/tikv.log
  3. 检查 PD 日志

    bash
    grep -i offline /tidb-deploy/pd-2379/log/pd.log
  4. 检查磁盘空间

    bash
    df -h /tidb-data
  5. 检查系统资源

    bash
    top
    free -h
    iostat -x

解决方案

  • 如果 TiKV 进程未运行,重启 TiKV 服务
  • 如果磁盘空间不足,清理磁盘或扩容
  • 如果系统资源不足,调整配置或扩容
  • 如果是硬件故障,更换硬件

5. PD Leader 频繁切换

问题描述

PD Leader 频繁切换,影响集群稳定性

排查步骤

  1. 查看 PD 日志

    bash
    grep -i leader /tidb-deploy/pd-2379/log/pd.log
  2. 检查 PD 节点状态

    bash
    tiup ctl pd -u http://[pd-host]:2379 member
  3. 检查网络延迟

    bash
    ping <pd-host1> -c 10
    ping <pd-host2> -c 10
  4. 检查系统时间

    bash
    date

解决方案

  • 确保 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 日志级别:

  1. 修改配置文件

    toml
    [log]
    level = "info"  # 可以设置为 debug、info、warn、error
  2. 动态调整

    sql
    SET GLOBAL tidb_log_level = 'info';
  3. 命令行参数

    bash
    tiup cluster edit-config [cluster-name]
    # 修改 log.level 参数
    tiup cluster reload [cluster-name] -R tidb

Q2: 如何查看 TiDB 慢查询日志?

A2: 可以通过以下方式查看 TiDB 慢查询日志:

  1. 直接查看日志文件

    bash
    grep -i slow /tidb-deploy/tidb-4000/log/tidb.log
  2. 使用 TiDB Dashboard

    • 登录 TiDB Dashboard
    • 点击左侧菜单中的 "慢查询"
    • 设置查询条件,查看慢查询日志
  3. 查询 mysql.slow_log 表

    sql
    SELECT * 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,tikv

Q4: 如何分析 TiKV 磁盘 I/O 问题?

A4: 可以通过以下方式分析 TiKV 磁盘 I/O 问题:

  1. 查看 TiKV 日志

    bash
    grep -i i/o /tidb-deploy/tikv-20160/log/tikv.log
  2. 使用 iostat 命令

    bash
    iostat -x 1
  3. 查看 RocksDB 统计信息

    bash
    tiup ctl tikv --host <tikv-host>:20160 rocksdb stats
  4. 查看 TiKV 监控指标

    • disk_read_bytes_total
    • disk_write_bytes_total
    • disk_io_time_seconds_total

Q5: 如何防止日志文件过大?

A5: 可以通过以下方式防止日志文件过大:

  1. 配置日志轮转

    • 修改组件的日志配置,设置日志轮转规则
    • 例如,每天轮转一次,保留 7 天的日志
  2. 调整日志级别

    • 在生产环境中,将日志级别设置为 info 或 warn
    • 避免使用 debug 级别,减少日志量
  3. 使用日志压缩

    • 对旧日志进行压缩,节省存储空间
    • 例如,使用 gzip 压缩旧日志
  4. 集中日志管理

    • 使用 ELK Stack 等工具集中管理日志
    • 便于日志分析和存储管理