📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 6.8-7.15

1. 错误异常的基本描述 #

Cannot delete indices that are being snapshotted 表示你试图删除的索引当前仍被快照流程占用。Elasticsearch 会先检查待删除索引是否包含在 SnapshotsService.snapshottingIndices(...) 的结果中;如果命中,就抛出 SnapshotInProgressException,阻止删除动作进入真正的元数据和路由删除流程。

常见现象 #

  • 调用删除索引接口时报错,尤其是批量删除历史索引、数据流 backing index 或归档索引时。
  • 错误信息通常会直接列出正在被快照的索引集合。
  • 如果删除是由生命周期管理或自动清理任务触发,同一时段还能看到快照作业没有结束。

典型报错与异常栈 #

常见日志形态类似下面这样:

SnapshotInProgressException: Cannot delete indices that are being snapshotted: [logs-2026.03.31].
Try again after snapshot finishes or cancel the currently running snapshot.

2. 为什么会发生这个错误 #

快照需要访问索引元数据和分片内容;而删除索引会直接移除这些对象。为了避免快照过程中对象被提前销毁,Elasticsearch 在删除入口先做保护性检查。只要索引仍在快照中,就不允许继续删除。

常见触发场景包括:

  • 定时快照与定时清理历史索引在同一个时间窗口执行。
  • 运维脚本一次性删除多个索引,其中部分索引正好被快照策略选中。
  • 快照耗时超出预期,导致后续删除脚本误判“备份已经结束”。
  • 需要删除的不是单个索引,而是整个模式匹配集合,结果把正在快照的索引也包含进去。

3. 如何排查和解决这个异常和解决这个异常 #

建议这样排查:

  1. 先检查快照状态,确认仓库、快照名以及目标索引是否仍在执行中的快照列表里。
  2. 还原删除请求的实际索引集合,确认是不是通配符或批量任务把不该删的索引一起带进来了。
  3. 检查删除来源,是人工删除、ILM 删除步骤,还是运维平台的清理任务。
  4. 如果快照异常卡住,再排查 master 日志、仓库可达性、对象存储延迟和分片任务进度。
  5. 删除动作恢复前,先确定已有备份是否成功生成,避免“删不掉时强制处理,删掉后又发现快照也没成功”。

排查时需要注意的问题 #

  • ignore_unavailable 不能绕过这个保护,因为这里不是“索引不存在”,而是“索引正处于不允许删除的运行态”。
  • 如果你看到删除脚本不断重试,应该先停掉重试,避免日志噪音掩盖真正的快照问题。
  • 在数据治理场景下,要区分快照备份成功后的删除,与快照还在运行时的删除冲突。

4. 如何解决这个错误 #

常用修复思路 #

  • 等当前快照完成后再执行删除,是最安全的处理方式。
  • 如果快照已经确认失败或卡死,先修复或取消快照,再继续删除索引。
  • 把删除任务改成两段式:先查询正在快照的索引并排除,再提交真正的删除请求。
  • 对自动归档和清理作业设置互斥,避免与快照同时运行。

后续注意事项与推荐建议 #

  • 如果删除动作依赖“快照成功后自动触发”,建议显式检查快照状态,而不是只靠时间间隔猜测。
  • 对历史索引清理任务增加幂等保护和冲突告警,避免持续失败后无人发现。
  • 对关键业务索引保留“最后一次可恢复快照”的校验流程,再允许进入删除阶段。

借助 INFINI 产品提升排障效率 #

  • INFINI Console 适合查看集群健康度、节点指标、索引状态、错误趋势和请求画像,帮助快速判断异常是局部问题还是系统性问题。
  • INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流、熔断、缓存和流量治理,尤其适合定位高频错误请求、异常重试和不合理 DSL。
  • 如果需要长期治理,建议把异常日志、慢查询、调用来源和变更记录统一接入监控面板,缩短从“发现问题”到“定位根因”的时间。

5. 小结 #

这个异常的核心不是删除 API 本身有问题,而是快照和删除两个动作在同一时刻争用同一批索引。把快照完成确认、删除前过滤和任务互斥做好,基本就能避免重复踩坑。

相关错误 #

附:日志上下文 #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

}  // Check if index deletion conflicts with any running snapshots
 SetsnapshottingIndices = SnapshotsService.snapshottingIndices(currentState; indicesToDelete);
 if (snapshottingIndices.isEmpty() == false) {
 throw new SnapshotInProgressException("Cannot delete indices that are being snapshotted: " + snapshottingIndices +
 ". Try again after snapshot finishes or cancel the currently running snapshot.");
 }  RoutingTable.Builder routingTableBuilder = RoutingTable.builder(currentState.routingTable());
 Metadata.Builder metadataBuilder = Metadata.builder(meta);