TiDB v7.6 长 SQL 报表引发 MVCC 版本堆积、GC 不回收,TiKV 磁盘持续暴涨求助

【TiDB 使用环境】生产金融业务
【TiDB 版本】v7.6.0
【部署架构】3PD+5TiKV+2TiDB,单机房 SSD,默认三副本 Raft
【业务场景】日间高频 DML 更新,每日凌晨跑全量大报表长查询(单 SQL 执行 3~5h)

长查询持有快照阻碍 GC 回收历史版本,磁盘膨胀;紧急停掉报表可快速触发 GC 落盘删数据,长期优化拆分大 SQL。

只能优化拆分大报表的长查询。

升级前建议先看 release notes,大版本之间有些参数默认值会变。另外生产环境升级建议先在一个 TiKV 节点灰度验证,观察一段时间没问题再全量升级。

超长报表 SQL 长时间不提交(3~5h)→ 导致 TiDB 把 start_ts 钉死在很早的时间 → GC safe_point 无法推进 → 历史版本无法清理 → MVCC 无限堆积 → TiKV 磁盘暴涨 → 读写越来越慢 → 雪崩

TiDB 的兼容性跟执行计划的生成机制有关,同样的 SQL 在 MySQL 和 TiDB 上的优化器决策可能不同,特别是子查询和 JOIN 的处理方式。迁移前建议用 SQL Plan Management 做下 SQL 兼容性扫描。

长报表 SQL 会持有固定快照(start_ts),阻塞 GC 安全点(safe_point)向前推进,旧数据版本、删除标记无法被 GC 清理,MVCC 版本不断堆积,最终导致磁盘占用持续飙升、集群读写性能下降。

解决方法: 对耗时 3~5h 的超大报表 SQL 进行拆分、改写,避免单条 SQL 长时间持有快照。

  • 加 TiFlash 做列存,隔离报表负载
  • 优化报表 SQL,更新统计信息
  • 调整 TiKV Compaction 与 PD 调度策略
  • 报表拆分 / 错峰执行,配置 spill-to-disk 防 OOM

gc回收后磁盘空间使用率能降到多少?

把超时SQL重新编写,看看有没有存储过程

这是一个典型的长查询阻塞 GC safe point 导致的 MVCC 版本堆积问题 。核心链条是:长 SQL(3~5h)持有快照 → safe point 无法推进 → GC 停止回收 → 版本堆积 → 磁盘暴增 → 读写性能恶化

  1. GC Safe Point 工作机制
    TiDB 的 GC 采用 MVCC(多版本并发控制),每当数据被修改时,旧版本不会直接删除,而是保留多个版本。GC 定期(默认 10 分钟)计算一个 safe point 时间戳,删除该时间戳之前的过期版本
    关键原则(TiDB v6.1.0+):safe point 不会超过正在执行中的事务的 start_ts,以保证长事务不读到被清理的数据 2122。这意味着:你的 3~5 小时长 SQL 会一直持有其开始时的快照版本,GC 无法清理这个时间点之后的历史版本,最终导致 MVCC 版本堆积

  2. 为什么磁盘持续暴涨
    长查询期间的 DML 更新:每条 UPDATE/DELETE 都会产生新的 MVCC 版本,这些版本因 safe point 阻塞而无法被 GC 回收,积累的版本占用大量磁盘空间

此话题已在最后回复的 7 天后被自动关闭。不再允许新回复。