0
0
0
0
博客/.../

TiDB_server_panic_total之index out of range

 克里克里克  发表于  2026-09-28

环境说明

v8.5.4,三节点混合部署

问题详细说明

TiDB集群启用Grafana alert告警之后,每隔约30分钟会触发TiDB_server_panic_total的告警。

告警信息

严重级别报警项

TiDB_server_panic_total

- 报警规则:

increase(tidb_server_panic_total[10m]) > 0

- 规则描述:

发生崩溃的 TiDB 线程的数量。当出现崩溃的时候会报警。该线程通常会被恢复,否则 TiDB 会频繁重启。

tidb日志

[2026/09/10 20:07:29.104 +08:00] [INFO] [queue.go:362] ["Start to refresh last analysis durations of jobs"] [category=stats] [sampled=] [2026/09/10 20:07:32.000 +08:00] [INFO] [refresher.go:161] ["Auto analyze triggered"] [category=stats] [job="NonPartitionedTableAnalysisJob:\n\tAnalyzeType: analyzeTable\n\tIndexes: \n\tSchema: testdb\n\tTable: test_tab\n\tTableID: 144\n\tTableStatsVer: 2\n\tChangePercentage: 0.537850\n\tTableSize: 1139022.00\n\tLastAnalysisDuration: 8993h47m43.512s\n\tWeight: 1.664103\n"] [2026/09/10 20:07:32.000 +08:00] [INFO] [worker.go:91] ["Job submitted"] [category=stats] [job="NonPartitionedTableAnalysisJob:\n\tAnalyzeType: analyzeTable\n\tIndexes: \n\tSchema: testdb\n\tTable: test_tab\n\tTableID: 144\n\tTableStatsVer: 2\n\tChangePercentage: 0.537850\n\tTableSize: 1139022.00\n\tLastAnalysisDuration: 8993h47m43.512s\n\tWeight: 1.664103\n"] [2026/09/10 20:07:32.003 +08:00] [INFO] [analyze.go:420] ["save analyze results in single-thread"] [category=stats] [buildStatsConcurrency=1] [saveStatsConcurrency=1] [2026/09/10 20:07:32.007 +08:00] [ERROR] [analyze.go:500] ["analyze worker panicked"] [category=stats] [recover="runtime error: index out of range [-1]"] [stack="github.com/pingcap/tidb/pkg/executor.(*AnalyzeExec).analyzeWorker.func1\n\t/workspace/source/tidb/pkg/executor/analyze.go:500\nruntime.gopanic\n\t/usr/local/go/src/runtime/panic.go:791\nruntime.goPanicIndex\n\t/usr/local/go/src/runtime/panic.go:115\ngithub.com/pingcap/tidb/pkg/executor.(*AnalyzeColumnsExecV2).analyzeColumnsPushDownV2\n\t/workspace/source/tidb/pkg/executor/analyze_col_v2.go:79\ngithub.com/pingcap/tidb/pkg/executor.analyzeColumnsPushDownEntry\n\t/workspace/source/tidb/pkg/executor/analyze_col.go:69\ngithub.com/pingcap/tidb/pkg/executor.(*AnalyzeExec).analyzeWorker\n\t/workspace/source/tidb/pkg/executor/analyze.go:527\ngithub.com/pingcap/tidb/pkg/executor.(*AnalyzeExec).Next.func1\n\t/workspace/source/tidb/pkg/executor/analyze.go:124\ngithub.com/pingcap/tidb/pkg/util.(*WaitGroupPool).Run.func1\n\t/workspace/source/tidb/pkg/util/wait_group_wrapper.go:213\ngithub.com/tiancaiamao/gp.worker\n\t/root/go/pkg/mod/github.com/tiancaiamao/gp@v0.0.0-20221230034425-4025bc8a4d4a/gp.go:37"] [2026/09/10 20:07:32.007 +08:00] [ERROR] [analyze.go:465] ["receive error when saving analyze results"] [category=stats] [error="runtime error: index out of range [-1]"] [2026/09/10 20:07:32.009 +08:00] [WARN] [analyze.go:582] ["analyze table `testdb`.`test_tab` has failed"] [category=stats] [partition=] ["job info"="auto analyze table all indexes, columns id, create_time, update_time with 256 buckets, 100 topn, 0.0950979540626163 samplerate"] ["start time"=2026/09/10 20:07:32.005 +08:00] ["end time"=2026/09/10 20:07:32.007 +08:00] [cost=2.246544ms] ["sample rate reason"="Row count in stats_meta is much smaller compared with the row count got by PD, use min(1, 15000/1.577321e+06) as the sample-rate=0.0950979540626163"] [error="runtime error: index out of range [-1]"] [2026/09/10 20:07:32.009 +08:00] [INFO] [tidb.go:278] ["rollbackTxn called due to ddl/autocommit failure"] [2026/09/10 20:07:32.009 +08:00] [WARN] [session.go:2176] ["run statement failed"] [schemaVersion=7286] [error="runtime error: index out of range [-1]"] [session="{\n \"currDBName\": \"testdb\",\n \"id\": 480962572,\n \"status\": 2,\n \"strictMode\": false,\n \"user\": {\n \"Username\": \"root\",\n \"Hostname\": \"192.168.1.115\",\n \"CurrentUser\": false,\n \"AuthUsername\": \"root\",\n \"AuthHostname\": \"%\",\n \"AuthPlugin\": \"mysql_native_password\"\n }\n}"] [2026/09/10 20:07:32.009 +08:00] [ERROR] [exec.go:63] ["auto analyze failed"] [category=stats] [sampled=] [sql="analyze table `testdb`.`test_tab`"] [cost_time=8.432934ms] [error="runtime error: index out of range [-1]"]

通过以上的TiDB日志可以明确是统计信息自动收集遇到的问题,可以根据提供的信息查看对应的表结构。

手动analyze该表也失败,同样的告警。

问题表结构

| test_tab | CREATE TABLE `test_tab` ( `id` bigint NOT NULL COMMENT 'id', `request_msg` json DEFAULT NULL COMMENT '请求报文', `response_msg` json DEFAULT NULL COMMENT '应答报文', `create_time` datetime DEFAULT NULL COMMENT '请求时间', `update_time` datetime DEFAULT NULL COMMENT '应答时间', `sys_interface_code` varchar(64) COLLATE utf8mb4_general_ci GENERATED ALWAYS AS (if(`request_msg` is not null and json_valid(`request_msg`), (json_unquote(json_extract(`request_msg`, _utf8mb4'$.head.sysInterfaceCode'))), null)) STORED COMMENT '接口编码', `cost_type` varchar(50) COLLATE utf8mb4_general_ci GENERATED ALWAYS AS (if(`response_msg` is not null and json_valid(`response_msg`), (json_unquote(json_extract(`response_msg`, _utf8mb4'$.head.costType'))), null)) STORED COMMENT '计费类型', `return_code` varchar(50) COLLATE utf8mb4_general_ci GENERATED ALWAYS AS (if(`response_msg` is not null and json_valid(`response_msg`), (json_unquote(json_extract(`response_msg`, _utf8mb4'$.head.returnCode'))), null)) STORED COMMENT '应答码' PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */, KEY `idx_time` (`create_time`), KEY `idx_sys_code` (`sys_interface_code`), KEY `idx_return_code` (`return_code`), KEY `idx_cost_type` (`cost_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_c

解决方案

通过查询git的issue,属于bug,8.5.7已修复该问题,可以选择升级版本。

  • 修复对依赖 JSON 等被跳过列类型的已索引存储生成列执行 ANALYZE TABLE 时可能发生 panic 的问题 #66359 #66918 @xhebox

临时方案

1)通过告警表的结构可以发现一点异常,1 是使用了json列,2 是使用了虚拟列且虚拟列上创建了索引,这两者都比较少见。既然是该表的统计信息收集问题,如果问题表不是核心表且数据量也少,可将该表统计信息lock,避免频发触发告警。

MySQL [(none)]> lock stats testdb.test_tab;

MySQL [(none)]> show stats_locked;

2)只收集部分列的统计信息,issue 里提到的 workaround 之一

ANALYZE TABLE `testdb`.`test_tab` PREDICATE COLUMNS; --只收集谓词列。

或

ANALYZE TABLE `testdb`.`test_tab` COLUMNS id, create_time; --收集指定列。

以下实证是收集json列触发的bug。

MySQL [(none)]> analyze table testdb.test_tab all columns; --收集所有列 ERROR 1105 (HY000): runtime error: index out of range [-1] MySQL [(none)]> analyze table testdb.test_tab columns request_msg; --json列 ERROR 1105 (HY000): runtime error: index out of range [-1] MySQL [(none)]> analyze table testdb.test_tab columns sys_interface_code; --正常字段类型,成功 MySQL [(none)]> analyze table testdb.test_tab columns return_code; --虚拟列,成功

拓展

统计信息谓词列

https://pingkai.cn/docs/tidb/stable/statistics#%E6%94%B6%E9%9B%86%E9%83%A8%E5%88%86%E5%88%97%E7%9A%84%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF

show column_stats_usage --查看表中哪些列是谓词列。

收集部分列的统计信息

当 TiDB 执行 SQL 语句时,优化器在大多数情况下只会用到部分列的统计信息。例如,WHERE、JOIN、ORDER BY、GROUP BY 子句中出现的列,这些被用到的列称为 PREDICATE COLUMNS。

  • 如果一个表有很多列,收集所有列的统计信息会产生较大的开销。为了降低开销,可以只收集选定列或者 PREDICATE COLUMNS 的统计信息供优化器使用。如果要持久化列配置以便将来沿用,参见持久化列配置。

注意

- 收集 PREDICATE COLUMNS 的统计信息的功能仅适用于 tidb_analyze_version = 2 的情况。

- TiDB v7.2.0 引入了系统变量 tidb_analyze_skip_column_types,该变量可以控制在执行 ANALYZE 命令收集统计信息时,跳过哪些类型的列的统计信息收集。该变量仅适用于 tidb_analyze_version = 2 的情况。

  • 如果要收集指定列的统计信息,请使用以下语法:

ANALYZE TABLE TableName COLUMNS ColumnNameList [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

其中,ColumnNameList 表示指定列的名称列表。如果需要指定多列,请使用用逗号 , 分隔列名。例如, ANALYZE table t columns a, b。该语法除了收集指定表中指定列的统计信息,将同时收集该表中索引列的统计信息以及所有索引的统计信息。

  • 如果要收集 PREDICATE COLUMNS 的统计信息,请使用以下语法:

ANALYZE TABLE TableName PREDICATE COLUMNS [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

TiDB 将每隔 100 * stats-lease 的时间将 PREDICATE COLUMNS 信息写入系统表 mysql.column_stats_usage。

以上语法除了收集指定表中 PREDICATE COLUMNS 的统计信息之外,将同时收集该表中索引列的统计信息以及所有索引的统计信息。

注意

- 如果系统表 mysql.column_stats_usage 中没有关于该表的 PREDICATE COLUMNS 记录,执行以上语句会收集该表中索引列的统计信息以及所有索引的统计信息。

- 对于任何被排除在此次统计信息收集(无论是手动列出列名,还是使用 PREDICATE COLUMNS)之外的列,它们的统计信息不会被覆盖。当执行新类型的 SQL 查询时,如果存在旧的统计信息,优化器将使用这些列的旧统计信息;如果从未收集过列的统计信息,则使用伪列统计信息。下一次使用 PREDICATE COLUMNS 的 ANALYZE 将收集这些列的统计信息。

  • 如果要收集所有列的统计信息以及所有索引的统计信息,请使用以下语法:

ANALYZE TABLE TableName ALL COLUMNS [WITH NUM BUCKETS|TOPN|CMSKETCH DEPTH|CMSKETCH WIDTH]|[WITH NUM SAMPLES|WITH FLOATNUM SAMPLERATE];

0
0
0
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论