报错是这么冒出来的。pymilvus 2.4.4 接 Milvus 2.4.1 单机版,批量 insert 两千条后立刻做统计,query 用 count(*) 得到 1980,同条件下 search 只回 1958 条,collection 用的是默认 Bounded 一致性,sleep 三百秒后差距还在,重连客户端也一样。

中间走过弯路,把「insert 之后没有 flush,部分数据只在内存里的 growing segment 中」当成主因,改完现象没变。

真正麻烦的地方在于,几个原因的现象几乎一样。Bounded 一致性下 query 读的是已确认时间戳,search 请求可能落到还没同步完的副本。另一种情况是向量索引还在 build 阶段,search 会跳过未建完的 segment。

还有一种情况,同一个别名指向了两个 collection,query 与 search 走了不同版本。

先看 collection 的加载状态和索引进度

python -c "from pymilvus import Collection;c=Collection('kb');print(c.num_entities, [i.params for i in c.indexes])"

随后把未落盘的数据刷一次再统计

python -c "from pymilvus import Collection;Collection('kb').flush()"

临时切成 Strong 一致性复测两条路径是否对齐

python -c "from pymilvus import connections, Collection;connections.connect(host='127.0.0.1', port='19530');c=Collection('kb', consistency_level='Strong');print(c.query(expr='id > 0', output_fields=['count(*)']))"

等前面都确认过,再确认别名是否指向了多个集合

python -c "from pymilvus import utility;print(utility.list_aliases())"

恢复的判定其实很直接。同一时刻 query 的 count 与 search 的返回条数一致,把结果按主键去重后没有缺号,切回 Bounded 后延迟仍在可接受范围。

提醒一点。Bounded 是吞吐和新鲜度的折中,写完就读的场景要么显式 flush,要么在检索前把一致性提到 Strong,别拿默认值去对账。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189