批量导入脚本看到 HTTP 200 就当成功,实际 items 数组里有 12 条 status 是 429,原因是 es_rejected_execution_exception。库里少了 12 条,脚本日志一片正常。乍看像缓存或者权限的锅,追下去往往不是。

resp = es.bulk(index="orders", operations=ops)
bad = [i for i in resp["items"] if i["index"]["status"] >= 300]
print(len(bad), bad[:2])

追下去是这么回事:bulk 的顶层状态码只表示请求本身被受理,每条文档的结果在 items 里。部分失败不会让整体返回非 2xx,不逐条检查就静默丢数据。429 是线程池队列满,属于可以重试的错误。

「bulk 部分失败」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。

能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。报错里带路径的,先去看那个路径在不在、权限对不对。

具体做法是,解析响应时遍历 items 收集 status 大于等于 300 的文档;只重试 429 和 503 这类可重试错误 400 直接记录;重试带指数退避 别在原地循环打满队列;把失败明细写到单独文件 便于补数核对。

验收就看一点,重跑后 bad 列表为空,_count 与源数据条数一致。

作者 9823189