案例:TiFlash 因 JSON 解码异常导致无法启动
时间:2026-04-13 版本:TiFlash v7.5.4
一、故障现象
TiFlash 进程反复崩溃重启,无法正常提供服务。日志中出现两类错误:
类型1:可捕获异常(Exception)
[FATAL] Code: 49, e.displayText() = DB::Exception:
DecodeJsonBinary: Unknown JSON Element Type:13
(while preHandleSnapshot region_id=1911061166, index=1086314, term=282)
类型2:段错误(SIGSEGV)
[ERROR] Received signal Segmentation fault(11).
[ERROR] Address: NULL pointer.
DB::StringObject<false>::toDebugString() const → TiKVKeyValue.h:66
DB::RegionBlockReader::read(...) → RegionBlockReader.cpp:101
二、根本原因
-
JSON 解码异常:TiKV 中存储了
JSON Element Type=13(MySQL 8.0 OPAQUE 类型)的数据,TiFlash v7.5.4 的解码器不支持该类型,触发异常后进一步引发 NULL 指针访问崩溃。 -
问题来源:表
physical_table_id=14179719的某列历史上经历过 DDL 类型变更,TiKV 中残留了旧 JSON 编码格式的数据。(还没完全确认) -
崩溃死循环:TiFlash 崩溃后自动重启,重启后继续尝试处理
snap/目录中残留的损坏 SST Snapshot 文件,再次崩溃,形成死循环。
三、涉及目录结构(TiFlash v7.5.x)
/ssd1/tiflash/deploy/data/
├── data/ # DeltaMerge 表数据(t_XXXXX 格式)
│ └── t_14179719/ # 问题表数据目录
├── flash/ # TiFlash Proxy 存储(KVStore)
│ ├── db/ # RocksDB,存储 Region 元信息
│ ├── raft-engine/ # Raft 日志引擎
│ ├── snap/ # ⭐ Snapshot SST 文件临时目录(关键)
│ ├── snap_v2/ # Snapshot v2 格式目录
│ └── import/ # SST 导入临时目录
├── metadata/ # TiFlash 表 Schema 元数据
└── page/ # PageStorage 数据
四、排障过程
Step 1:确认问题 Region
grep "preHandleSnapshot\|while preHandleSnapshot" /ssd1/tiflash/deploy/log/tiflash.log \
| grep -oE "region_id=[0-9]+" | sort -u
# 结果:region_id=1911061166, region_id=2683642138
Step 2:确认问题表
grep "preHandleSnapshot" /ssd1/tiflash/deploy/log/tiflash.log \
| grep -oE "physical_table_id=[0-9]+" | sort -u
# 结果:physical_table_id=14179719
Step 3:TiDB 侧移除 TiFlash 副本
-- 找到表名
SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.tables
WHERE TIDB_TABLE_ID = 14179719;
-- 移除 TiFlash 副本
ALTER TABLE <table_name> SET TIFLASH REPLICA 0;
Step 4:确认 PD 侧已无 TiFlash Peer
tiup ctl:v7.5.4 pd -u http://<pd_addr>:2379 region 1911061166
# 确认 peers 列表中没有 tiflash store
Step 5:用 tikv-ctl 将问题 Region 标记为 tombstone
# 注意:--data-dir 必须指向 flash/ 目录,不是 data/ 目录
tiup ctl:v7.5.4 tikv --data-dir=/ssd1/tiflash/deploy/data/flash \
tombstone -r 1911061166 --force
tiup ctl:v7.5.4 tikv --data-dir=/ssd1/tiflash/deploy/data/flash \
tombstone -r 2683642138 --force
⚠️ 注意:tombstone 只处理 Region 元信息,不会删除 snap/ 目录中已下载的 SST 文件!
Step 6:清理 snap/ 目录中残留的损坏 SST 文件(关键步骤)
# 查看 snap 目录,确认问题 Region 的文件
ls /ssd1/tiflash/deploy/data/flash/snap/
# 文件格式:rev_<region_id>_<term>_<index>_<cf>.sst
# 对 snap 目录中所有 Region 也执行 tombstone
tiup ctl:v7.5.4 tikv --data-dir=/ssd1/tiflash/deploy/data/flash \
tombstone -r 2429432991,2435607708,2631123527,2635411770 --force
# 清空 snap 目录 (创建一个 snap_bak 然后把有问题的 region SST 移动到 bak 文件夹)
五、关键经验教训
1. tikv-ctl tombstone 对 TiFlash 的使用限制
--data-dir必须指向flash/目录(不是data/或data/data/)- tombstone 只清理元信息,不清理
snap/目录中已下载的 SST 文件
2. snap/ 目录是关键
- TiFlash 崩溃循环的根因往往是
snap/目录中残留的损坏 Snapshot SST 文件 - 执行 tombstone 后必须同步清理
snap/目录,否则 TiFlash 重启后仍会处理这些文件并崩溃 snap/中的文件是临时传输文件,删除后 TiKV 会重新发送,不丢数据
六、快速诊断命令
# 找出所有崩溃相关的 Region
grep "preHandleSnapshot" /ssd1/tiflash/deploy/log/tiflash.log \
| grep -oE "region_id=[0-9]+" | sort -u
# 找出所有涉及的表
grep "preHandleSnapshot" /ssd1/tiflash/deploy/log/tiflash.log \
| grep -oE "physical_table_id=[0-9]+" | sort -u
# 查看 snap 目录中的 Region 文件
ls /ssd1/tiflash/deploy/data/flash/snap/ \
| grep -oE "rev_[0-9]+" | sort -u
# 查询 TiFlash store_id
tiup ctl:v7.5.4 pd -u http://<pd_addr>:2379 store \
| grep -B2 -A10 "tiflash" | grep '"id"'
(备注:以上内容由AI总结(笑)但是总体处理过程是和文章中一致的。各位运维同行们还是得好好利用上AI,毕竟处理的时候官方社区也没有搜到经验,有些时候AI确实是可以辅助很多判断的)