执行流程
第一步
TiDB 生成执行计划
TopN(offset 50 count 200)
↓
TableReader
↓
TopN pushdown
↓
TableFullScan
逻辑是:
Top 250
不是 200。
因为:
offset + count
第二步
TopN 下推到 TiKV
每个 Region 都会执行:
Top 250
即:
region1
返回
0-100
最多100行
region2
返回
101-200
最多100行
region3
返回
201-300
最多100行
但:
只需要
250
第三…
为什么 order by limit 慢
因为:
每个 region 都要返回 Top250
而不是:
只要200
所以:
region数越多
分页越慢
特别是:
limit 100000,10
会变成:
Top100010
非常重。
如何确认是哪种原因
需要看系统表。

查看慢 SQL
select *
from information_schema.slow_query
where query like ‘%point_get%’
order by time desc
limit 10;
关注:
Write Conflict
Lock wait
Backoff
TxnRetry

查看事务重试
select *
from information_schema.cluster_tidb_trx;
看:
waiting_start_time
state

查看锁
select *
f…
写冲突(最常见)
典型场景:
update user set age=20 where id=1;
同时另一个事务:
select * from user where id=1;
或
update user set age=21 where id=1;
TiDB 会发生:
Write Conflict
或
Lock Conflict
流程:
事务A锁住key
↓
事务B point_get
↓
等待锁
↓
超时
↓
事务重试
就会看到:
point_get 3秒
txn retry
三、为什么 point_get 会变成 3 秒
因为 TiDB …
基本可以判断是 TiDB 事务冲突或锁等待导致的 point_get 延迟 。
核心原因
TiDB 的 SLOW_QUERY / CLUSTER_SLOW_QUERY 是内存表 / 临时汇总表
它不是普通 InnoDB 表,不会自动在事务中刷新。
pymysql 默认开启自动提交 = False,会进入一个长事务
你在 Python 里第一次连接后,就进入了一个事务快照。
之后慢查询新产生的数据,在这个事务里看不见。
而你在命令行:
• 要么每条语句自动提交
• 要么每次重连新会话
所以能查到最新数据。
这种情况在 TiDB 里非常典型,不是时区问题,而是 TiDB 慢查询表的会话可见性 / 刷新机制 + pymysql 默认事务隔离级别
TiKV 未释放空间的原因
1)SST import 临时文件
路径
/data1/tidb-data/tikv-20160/import
里面会有:
.temp
.sst
这些是 restore 过程产生的。
如果 restore 中断:
不会自动清理。
2)删除库只是逻辑删除
你执行了:
drop database
但:
数据不会立即删除
因为 TiDB 是:
MVCC + GC 回收
删除后:
数据进入:
GC 等待阶段
只有 GC 后才真正释放。
3)GC 停在凌晨
你说:
gc时间停在凌晨
说明:
GC 没推进
检查:
mys…
您提到:
• 部分 TiKV 磁盘空间爆满
• GC 时间停在凌晨
这是典型的 GC 积压导致空间未释放 问题。当 BR 恢复失败中断时,会产生大量临时数据和版本堆积。
解决方案
紧急释放空间(已爆满节点)
– 检查当前 GC 状态
SELECT * FROM mysql.tidb WHERE VARIABLE_NAME LIKE ‘%gc%’;
– 手动触发 GC(谨慎操作)
UPDATE mysql.tidb SET VARIABLE_VALUE = DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 HOUR), ‘%Y%m%d-%H:%M:%…
强制回表(临时规避)
对于涉及BIT类型字段的查询,强制使用TableReader而非IndexOnlyScan:
BIT类型编码问题
TiDB的BIT类型在存储和索引编码时存在特殊处理。当使用覆盖索引时,优化器直接从索引读取数据而不回表,此时BIT类型的解码可能出现错误。
索引构建时的数据不一致
根据TiDB 7.5.1 Release Notes,虽然修复了"BIT type columns might cause query errors due to decode failures"(#49566, #50850, #50855),但你的案例表明在复合索引+覆盖扫描场景下仍有问题。
1 * 确认 TiDB 上已无 TiFlash 副本
SELECT TABLE_SCHEMA, TABLE_NAME, REPLICA_COUNT, AVAILABLE
FROM information_schema.tiflash_replica;
你已经做了,结果为空,说明 TiDB 侧没问题。
检查 PD 上 region 的分布
pd-ctl store
看看这些 Pending Offline 的 TiFlash 是否还在 region 分配表里。
如果 region 还在,但 table id 已不存在,就需要清理 TiFlash 本地残留 region。
残留 Region 或 Replica
即使表副本数量为 0,一些历史 region 或 snapshot 还可能绑定了这些 TiFlash 节点。
这些 region 数据 TiFlash 尝试 flush 时找不到表对应的 metadata,就会不断报错并阻塞下线。
TiFlash 节点本地存储残留旧数据
下线过程 TiFlash 会清理本地 region,如果 region 对应的表已经不存在,但本地数据未能清理干净,节点会一直在 Pending 状态。
最常见触发原因

生产中出现这种错误,一般是下面几种。

目录权限被修改(最常见)
例如:
/data/tidb/tikv/
原来:
tikv:tikv
后来被改成:
root:root
或
chmod 改错。
导致:
TiKV 无法写 rocksdb.info。
检查
在 TiKV 节点执行:
ls -ld /X
ls -l /X
看权限。
例如:
drwx------ root root
就会报错。
正确权限
tikv tikv
755
或
700
即可。

日志目录被删除
例如:
rm -rf rocksdb.info
rm -r…
更偏向环境问题,不是 TiKV 核心 BUG
原因:
TiKV 使用 Rust。
Rust 中:
unwrap()
如果失败会 panic。
TiKV 设计是:
日志目录初始化失败 → 直接 panic → 重启
这是为了避免:
日志不可写但服务继续运行。
属于:
Fail Fast 机制
为什么不能长期打开
因为它会产生额外开销。
#会触发 Profile 采样
例如:
CPU Profile
会:
采样CPU调用栈
统计执行路径
生成火焰图
这本身会消耗 CPU。
虽然不大,但在高并发生产环境会增加负担。
手动分析本质是:
抓取性能 Profile 数据
类似于:
CPU profile
Memory profile
Mutex
Goroutine
SQL执行情况
内部调用的是:
pprof
trace
metrics
tikv/tidb profile
属于:
性能采样分析