创建索引时提示1105 - runtime error: invalid memory address or nil pointer dereference

【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)的索引了。

目录权限对吗

root权限777,应该没问题把

看看tidb日志能不能找到点线索

什么客户端

navicat17的免费版本。


豆包回答

1 个赞

从错误日志来看,这个 panic 发生在 TiDB 的后台回填(backfill)任务执行过程中,具体是 backfillDistExecutorgetBackendCtx 方法出现了空指针引用(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 前后的上下文,包含 ddldisttask 相关日志)。
  • 记录表结构(SHOW CREATE TABLE 结果)、索引信息、TiDB 版本(SELECT tidb_version();)。
  • 到 TiDB 官方 GitHub Issues社区论坛 提交问题,附上上述信息,以便开发团队定位修复。

临时规避方案

如果需要紧急添加索引,可尝试绕过分布式回填逻辑(适用于小表):

  • 先关闭分布式 DDL(仅临时使用,大表不建议):

sql

SET GLOBAL tidb_enable_distributed_ddl = OFF;
  • 执行索引添加操作,完成后再开启:

sql

SET GLOBAL tidb_enable_distributed_ddl = ON;

注意:关闭分布式 DDL 后,索引添加会在单个 TiDB 节点执行,可能影响该节点性能,仅建议在小表上临时使用。

2 个赞

在日志里查一下runtime error、invalid memory address 或 nil pointer dereference,查看错误发生时的上下文(如 DDL 处理流程、组件调用栈),再来判断下

1 个赞

看下你的/tmp目录,空间够不够,如果空间足够,就把/tmp目录设置吃777权限。

1 个赞

想到一块了

1 个赞

空间还有40G,肯定是够的,目录权限已经是777了。
有些表建索引是成功的,这个表不行。
但是这个表也就不到10万条数据。

1 个赞

今天测试建这个索引又成功了。
中途没有对数据库配置做任何修改。
而且现在数据量应该是更大了。
之前是3秒就失败,今天看日志花了6.4秒

1 个赞

你系统是虚拟机吗?如果是虚拟机,查一下虚拟机的磁盘,是不是精简制备?物理机的话查一下硬盘IO速度。

1 个赞

正常物理机。

1 个赞

这个说的很详细

1 个赞

看一下目录权限对不对?是不是ddl创建的时候 元数据缺失了?

1 个赞

触发BUG了吗这是