InfluxDB使用shard作为底层时间序列数据的物理存储单元,每个shard对应一个时间区间的TSM文件集合。当磁盘故障或异常关机导致某个shard的索引或数据块损坏时,查询若命中该shard就会触发tsm1: read error之类的异常,使整个SELECT语句失败。理解shard与query planner的映射关系,是绕过损坏片段的前提。

识别并定位损坏的shard
在节点日志中通常会出现类似engine: error opening shard的条目,其中包含了具体的shard ID与数据库名。我们也可以主动用influxd inspect report-disk或者influxd inspect verify-seriesfile来扫描,不过最直接的方式是查询系统视图SHOW SHARDS,然后逐个检查对应目录下的.tsm文件能否被打开。InfluxDB在启动时会尝试加载所有shard,若某shard损坏,该shard的状态可能显示为error。
定位到具体shard后,需要记录它所属的database、retention policy以及起止时间。因为查询计划生成时,InfluxDB会根据WHERE中的时间范围映射到特定shard,所以我们只要让查询不触及该时间窗,就能避开损坏文件。例如shard覆盖2023-05-01到2023-05-08,那么在该区间外的查询仍可正常返回。
有时损坏并非整个shard不可用,而是个别TSM块CRC校验失败。可以通过如下命令尝试导出未损坏部分:
influxd inspect export-block -datadir /var/lib/influxdb/data -waldir /var/lib/influxdb/wal -out /tmp/export -database metrics -rp autogen -shard 42
在查询层跳过损坏shard的常用方案
最简单的方法是改写业务查询,用时间条件排除故障shard。假设shard 42负责2023-05-01至2023-05-08,我们可以把原查询SELECT mean(value) FROM cpu WHERE time > '2023-04-01'改为两个UNION类的子查询,分别查之前与之后的区间,中间缺口由应用层忽略。InfluxDB本身不支持SQL风格UNION,但可以用Continuous Query或者应用代码分两次请求再合并。
另一个做法是临时将损坏shard所属的retention policy设为不活跃,或新建一个同名RP但不同duration,把写入导向新shard,旧RP的损坏shard不再有新数据写入,查询时显式指定新RP。这样老数据缺失该区间,但整体服务不中断。示例:
-- 原查询可能命中损坏shard SELECT mean(usage) FROM "autogen".cpu WHERE time > now() - 30d -- 改为仅查新RP SELECT mean(usage) FROM "autogen_new".cpu WHERE time > now() - 30d
对于使用Flux的用户,可以用range函数精确避开坏区间,并利用filter剔除异常值。Flux在底层也会按shard做分片读取,只要时间范围不重叠损坏shard,就不会打开坏文件。下面是一段Flux示例:
from(bucket: "metrics/autogen") |> range(start: 2023-05-09T00:00:00Z, stop: now()) |> filter(fn: (r) => r._measurement == "cpu")
运维层面的临时处置与恢复对比
在紧急恢复阶段,有人会选择直接删除损坏shard目录,让InfluxDB在重启时重建空shard。这种做法能让查询不再报错,但对应时间窗数据永久丢失。若业务允许丢部分历史点,这是最快的恢复手段;若数据必须保留,则应先对磁盘做镜像,再尝试用influxd recover工具提取完好的series。
长期来看,应为关键库配置复制因子大于1的集群模式,或使用异地备份。单节点下,可设置较短的shard duration,这样即使一个shard坏掉,影响的时间范围也更小,跳过成本更低。下表对比了三种处理方式:
| 方案 | 查询连续性 | 数据损失 | 操作复杂度 |
|---|---|---|---|
| 时间条件绕过 | 高 | 无 | 低 |
| 删除坏shard目录 | 高 | 该shard全部 | 极低 |
| 换RP写新数据 | 中 | 无新增损失 | 中 |
实际处理中,建议先通过时间绕过保证线上查询,再在低峰期用备份修复损坏shard。切忌在未经备份时直接rm -rf shard文件夹,否则可能连带wal日志造成更严重的写入错乱。理解存储引擎的shard隔离机制,才能在故障面前做到心中有数。
InfluxDBshard_corruptionquery_skip修改时间:2026-08-17 08:04:13