【TiDB 使用环境】生产环境
【TiDB 版本】8.1.2
【操作系统】centos7.9
【部署方式】物理机部署80H64G磁盘50G+1.7T * 3
【集群数据量】1G
【集群节点数】3
【问题复现路径】做过哪些操作出现的问题
创建索引,第一次提示没有文件夹,到服务器上手动创建了文件夹/tmp/tidb/tmp_ddl-4000。
然后再添加索引,提示1105 - runtime error: invalid memory address or nil pointer dereference
【遇到的问题:问题现象及影响】无法创建索引
【资源配置】进入到 TiDB Dashboard -集群信息 (Cluster Info) -主机(Hosts) 截图此页面
【复制黏贴 ERROR 报错的日志】
【其他附件:截图/日志/监控】
新索引字段类型 varchar(40)
应该和类型无关,因为之前已经有一个varchar(40)的索引了。
从错误日志来看,这个 panic 发生在 TiDB 的后台回填(backfill)任务执行过程中,具体是 backfillDistExecutor 的 getBackendCtx 方法出现了空指针引用(nil pointer dereference)。这通常与 TiDB 在处理分布式索引回填任务时的内部逻辑异常相关,可能的原因和解决思路如下:
1. 确认 TiDB 版本是否存在已知 bug
这类底层执行器的空指针问题,大概率是 TiDB 特定版本的 bug。建议先检查你当前使用的 TiDB 版本,然后参考以下步骤:
- 查看 TiDB 的 Release Notes,确认是否有关于 “backfill”、“disttask” 或 “index backfilling” 的 bug 修复(尤其是空指针相关的修复)。
- 如果使用的是较旧的版本(如 v6.x 之前),强烈建议升级到最新的稳定版(如 v7.5+ 或 v8.1+),这类底层执行框架的问题在新版本中通常会被修复。
2. 检查表结构和索引状态
回填任务通常与添加索引相关,表结构或索引的异常可能触发该问题:
- 确认当前操作的表是否存在结构不一致(如分区表的特殊配置、表已被删除但元数据残留等):
sql
-- 检查表的基本信息
SHOW CREATE TABLE your_table_name;
-- 检查表的索引状态
SHOW INDEX FROM your_table_name;
-- 检查表的健康状态
ADMIN CHECK TABLE your_table_name;
- 如果表存在损坏或元数据不一致,可尝试通过
ADMIN REPAIR TABLE 修复(需谨慎,建议先备份数据)。
3. 清理残留的分布式任务
如果回填任务失败后残留了未完成的分布式任务,可能导致后续任务再次触发异常:
sql
-- 查看所有分布式任务(TiDB v5.4+ 支持)
SELECT * FROM information_schema.dist_tasks;
-- 查看 DDL 任务状态(索引添加属于 DDL 操作)
SELECT * FROM information_schema.ddl_jobs WHERE table_name = 'your_table_name' ORDER BY start_time DESC;
- 如果发现状态异常的任务(如
running 状态持续很久但无进展),可尝试终止任务:
sql
-- 终止指定 DDL 任务(需替换 job_id)
ADMIN CANCEL DDL JOB <job_id>;
- 若分布式任务表中存在残留任务,可通过 TiDB 控制台或
pd-ctl 清理(需谨慎操作,建议参考官方文档)。
4. 调整回填任务的资源配置
在大表上添加索引时,回填任务可能因资源不足(内存、并发)触发异常,可尝试调整相关配置:
- 临时调大回填任务的内存限制(通过 TiDB 配置文件或动态变量):
sql
-- 调整单个 backfill 线程的内存限制(默认 128MB,可适当增大)
SET GLOBAL tidb_ddl_backfill_memory_quota = 268435456; -- 256MB
-- 降低回填并发度,减少资源竞争
SET GLOBAL tidb_ddl_reorg_worker_cnt = 4; -- 默认 4,可根据集群负载调整
- 避免在业务高峰期执行大表索引添加操作,选择低峰期执行。
5. 收集信息并上报官方
如果以上步骤无法解决问题,大概率是 TiDB 的未修复 bug,建议收集详细信息并上报:
- 收集 TiDB 节点的完整日志(重点是 panic 前后的上下文,包含
ddl、disttask 相关日志)。
- 记录表结构(
SHOW CREATE TABLE 结果)、索引信息、TiDB 版本(SELECT tidb_version();)。
- 到 TiDB 官方 GitHub Issues 或 社区论坛 提交问题,附上上述信息,以便开发团队定位修复。
临时规避方案
如果需要紧急添加索引,可尝试绕过分布式回填逻辑(适用于小表):
sql
SET GLOBAL tidb_enable_distributed_ddl = OFF;
sql
SET GLOBAL tidb_enable_distributed_ddl = ON;
注意:关闭分布式 DDL 后,索引添加会在单个 TiDB 节点执行,可能影响该节点性能,仅建议在小表上临时使用。
2 个赞
我是火炎焱燚
(Ti D Ber 9 Dh P An J6)
11
在日志里查一下runtime error、invalid memory address 或 nil pointer dereference,查看错误发生时的上下文(如 DDL 处理流程、组件调用栈),再来判断下
1 个赞
lllzd
(时光旅行者)
13
看下你的/tmp目录,空间够不够,如果空间足够,就把/tmp目录设置吃777权限。
1 个赞
空间还有40G,肯定是够的,目录权限已经是777了。
有些表建索引是成功的,这个表不行。
但是这个表也就不到10万条数据。
1 个赞
今天测试建这个索引又成功了。
中途没有对数据库配置做任何修改。
而且现在数据量应该是更大了。
之前是3秒就失败,今天看日志花了6.4秒
1 个赞
lllzd
(时光旅行者)
17
你系统是虚拟机吗?如果是虚拟机,查一下虚拟机的磁盘,是不是精简制备?物理机的话查一下硬盘IO速度。
1 个赞
kiiz
(Ti D Ber Ek Uo9 Soh)
20
看一下目录权限对不对?是不是ddl创建的时候 元数据缺失了?
1 个赞