TiDB高并发场景下如何合理拆分热点,保障事务稳定性?

一个好的问题描述有利于社区小伙伴更快帮你定位到问题,高效解决你的问题

【TiDB 使用环境】生产
【TiDB 版本】v8.0.0
【问题描述】业务高并发写入存在热点数据,易引发写冲突、性能抖动,想了解热点识别方法与规范拆分优化方案。

【期望得到的帮助】

  1. 热点定位常用手段有哪些
  2. 业务层面与数据库侧标准有什么好的优化方案
  3. 高并发下事务编写规范有哪些

热点先看 Dashboard 流量可视化和 tikv_hot_write。业务侧避免自增主键、时间热键,改用离散主键或加盐。库侧可开 hotspot scheduler、合理 split、控制事务大小。事务尽量短、少跨行、冲突键分开提交。

1 个赞
  1. 业务层哈希打散热点主键:避免自增 ID 单点写入,用分片键 / 前缀哈希打散,把写入分散到多个 Region,解决单 Region 写热点。
  2. 避免单行高频更新:计数器不要单条行累加,做分桶计数,内存合并再落库。
  3. 表分区拆分:时间维度热点按 Range 分区,热点数据隔离到独立分区 Region。
  4. 索引热点规避:避免时间、自增列作为唯一索引造成索引热点。
  5. 控制事务大小,大事务拆小,减少锁持有时长,减少冲突重试。

热点定位及解决可以看下官方文档:https://docs.pingcap.com/zh/tidb/stable/troubleshoot-hot-spot-issues/#gatsby-focus-wrapper

大佬能详细分享下吗

热点问题在TiDB里确实常见,给你几个实战经验:

热点定位:

  • 用grafana看TiKV的Written Bytes和Key Rate,哪个TiKV明显偏高就是热点
  • information_schema.tidb_hot_regions表,能直接看到热点region分布
  • 业务日志里抓慢查询,看是否有同一行/同一前缀的写入

拆分优化:

  • 业务侧:给索引加随机后缀,比如用户ID+时间戳哈希,避免自增主键集中写
  • 表结构:如果主键是自增,改成AUTO_RANDOM,或者用SHARD_ROW_ID_BITS=4打散
  • 调整region大小,split-table配合预拆分,让数据均匀分布

事务编写规范:

  • 尽量小事务,别一把梭,单事务行数控制在1000以内
  • 避免SELECT FOR UPDATE范围过大,走主键或唯一索引
  • 重试机制要开,tidb_disable_txn_auto_retry设0,但注意幂等性

先按这几个方向排查,搞不定再贴监控图上来。

业务层高并发的放redis,模糊查询放es。

先通过Dashboard热力图定位热点,并在数据库侧使用 AUTO_RANDOM 主键、打散 Region 结合业务侧,离散化 Hash 拆分来打散热点。

向大佬学习

1、热点问题,应用使用了雪花算法,或者数据库使用了AUTO_RANDOM基本可以消除热点问题,TiDB内部算法会自动打散。
2、 – 查看热点表

SELECT * from information_schema.tidb_hot_regions;

TIDB_HOT_REGIONS 表各列字段含义如下:
TABLE_ID:热点 Region 所在表的 ID。
INDEX_ID:热点 Region 所在索引的 ID。
DB_NAME:热点 Region 所在数据库对象的数据库名。
TABLE_NAME:热点 Region 所在表的名称。
INDEX_NAME:热点 Region 所在索引的名称。
REGION_ID:热点 Region 的 ID。
TYPE:热点 Region 的类型。
MAX_HOT_DEGREE:该 Region 的最大热度。
REGION_COUNT:所在实例的热点 Region 数量。
FLOW_BYTES:该 Region 内读写的字节数量。

– 查看历史热点 Region 的相关信息

SELECT
UPDATE_TIME,
REGION_ID,
STORE_ID,
PEER_ID,
IS_LEARNER,
IS_LEADER,
TYPE,
table_id,
db_name,
table_name
FROM
information_schema.tidb_hot_regions_history
WHERE
table_id = 35748
AND update_time > ‘2026-06-24 20:40:00’
AND update_time < ‘2020-06-25 21:40:00’
AND type = ‘read’;
– 查询出热点表,可以做分片处理