应手动干预region split:当表刚创建即写入大量数据或主键单调时,即使region未达64mb也会因写热点导致请求集中于单个leader,此时需人工分裂;关键判断点是region大小未触发自动分裂但hot_score持续>5000且leader_store_id长期固定。

什么时候该手动干预 Region Split,而不是等自动分裂
自动分裂(默认64MB)只看大小,不看流量。当某张表刚创建、立刻写入大量数据(比如导入10GB订单日志),或主键高度单调(如auto_increment ID、时间戳ID),哪怕 Region 还不到64MB,也会因所有写请求打到同一个 Region 的 Leader 上,形成写热点——此时自动分裂根本来不及触发,必须人工介入。
- 典型现象:
pd-ctl -u http://pd:2379 hot read/region显示某个 Region 的hot_score持续 > 5000,且leader_store_id长期固定在单个 TiKV 节点 - 关键判断点:Region 大小 read_keys 或
write_keys每秒超 5w,且 PD 调度器未主动 split(pd-ctl operator list无 pending 的 split operator) - 不要等:一旦发现
tidb_server_handle_query_duration_seconds_bucket99分位突增,同时 TiKV 的raftstore_propose_wait_time升高,说明 propose 队列已在积压,再拖几秒就可能触发 leader 切换失败
手动 Split 的两种实操路径及适用场景
不是所有“手动 split”都一样:预切分(pre-split)针对新建表,运行时 split 针对已承载流量的热 Region。选错路径会导致 Region 空转或调度失效。
-
新建表预切分:用
SPLIT TABLE t BETWEEN (0) AND (100000000) REGIONS 16。适用于批量导入前,且主键可预估范围(如订单ID从1开始递增)。注意:若主键是VARCHAR类型手机号,需先用SELECT HEX('13800138000')转成字节序再算边界 -
运行中热 Region 强制分裂:先查出热点 Region ID:
pd-ctl region key "t_123_rk_123",再执行pd-ctl operator add split-region 12345 --policy=scan。注意:不能对正在被 GC 的 Region(state == "TOMBSTONE")操作,否则返回"region not found" - 避坑:不要用
split-region-size配置项“间接干预”——它只影响后续自动分裂阈值,对当前热点无效;且改完要等下一个 Region 达到新阈值才生效,完全不解决燃眉之急
split-region-size 参数调优的真实影响链
把 split-region-size 从64MB改成128MB,看似只是“少分裂几次”,实际会连锁改变 Region 数量、GC 压力、PD 调度负载三件事。
- Region 数量下降约40%(实测集群从8.2w→4.9w),但单个 Region 平均读写 QPS 上升,
raftstore_apply_wait_time方差变大——意味着部分 Region 开始吃紧 - GC 压力降低:旧 Region 的 tombstone 状态存留时间缩短,
tikv_engine_size_bytes{cf="default"}曲线更平滑 - PD 调度负担加重:balance-region 调度器每分钟需搬运的 Peer 数据量上升,
pd_scheduler_balance_region_operator_duration_seconds99分位从200ms跳到850ms - 慎用场景:小表(ATTRIBUTES='merge_option=deny' 禁止合并,而非调大分裂阈值
为什么 pd-ctl split-region 经常失败?三个硬性限制
不是命令输错,而是 TiKV 内部有不可绕过的校验逻辑。常见报错如 "failed to split: region not found" 或 "split key out of range",本质是违反了以下任一条件:
- 目标 Region 必须处于
State == "Normal"(不能是Merging、Pending或Tombstone)——用pd-ctl region 12345查state字段确认 - 指定的 split key 必须严格落在该 Region 的
start_key和end_key之间,且不能是空 key("")或全零 key(\x00\x00...) - 该 Region 的 peer 当前不能正在接收 snapshot(
pending_snapshot_count > 0),否则 Raft 日志 apply 会阻塞,split 操作被拒绝
最易忽略的一点:TiDB 5.4+ 默认开启 split-table = true,但若表建在旧版本集群上且未执行 ALTER TABLE t ATTRIBUTES='split=true',则该表仍按 legacy 模式管理,pd-ctl 对其 split 操作会被静默忽略——得先补这个 DDL。










