Skip to content

[Bug][数据一致性] index_file 的 Milvus+PostgreSQL 双写用并发 gather + best-effort 回滚,回滚失败残留单边数据 #878

Description

@Alex-Fleet

标题: [Bug][数据一致性] index_file 的 Milvus+PostgreSQL 双写用并发 gather + best-effort 回滚,回滚失败残留单边数据

正文:

问题

backend/package/yuxi/knowledge/implementations/milvus.py(约 534 行)_insert_chunks_to_stores 同时写 PostgreSQL(chunk_repo.batch_upsert)与 Milvus(collection.insert):

pg_task = chunk_repo.batch_upsert(self._build_chunk_pg_records(kb_id, chunks))
milvus_task = asyncio.to_thread(_insert_milvus_records)
results = await asyncio.gather(pg_task, milvus_task, return_exceptions=True)
...
await chunk_repo.delete_by_file_id(file_id)   # rollback,失败仅 log
try:
    await self._delete_file_chunks_from_milvus(collection, file_id)
except Exception as cleanup_error:
    logger.error(...)
  1. 任一失败后回滚是 best-effort:回滚的异常只记日志,若回滚时对端网络异常,留下"PG 有 chunk 但 Milvus 没有"或反之的单边数据
  2. 嵌入中途某批失败时已写批次先落库,文件状态置 ERROR_INDEXING,需人工重索引才能收敛;状态机无自动重试。

建议

  1. 双写改为以 PG 为准 + 幂等重试:PG 写入成功后,Milvus 插入可重试(插入按 file_id/chunk_id 幂等),不依赖并发 gather 的强一致;
  2. 失败进入补偿/重试队列,而不是置 ERROR_INDEXING 就放弃;
  3. 增加对账:比对 PG chunks 与 Milvus 集合中按 file_id 的向量,定期清理单边残留。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions