先看现象。Chroma 0.5.5 的 PersistentClient 指向同一个目录,两个采集进程同时 add,第二个进程报 sqlite3.OperationalError: database is locked,重试三次仍然失败,改成单进程写就正常,给 add 外面套 retry 也没用。

把日志和配置对完,能解释这个现象的基本就这几处。SQLite 写锁同一时刻只允许一个写者。也可能是默认 busy_timeout 只有 5 秒。

另外,两个进程的 journal 模式不一致。

少数情况下是目录放在网络盘上文件锁本身不可靠。

第一件事是查当前日志模式与超时

python -c "import sqlite3;c=sqlite3.connect('chroma.sqlite3');print(c.execute('pragma journal_mode').fetchone(),c.execute('pragma busy_timeout').fetchone())"

再往下把 busy_timeout 调到 30 秒再试

python -c "import sqlite3;c=sqlite3.connect('chroma.sqlite3',timeout=30);c.execute('pragma busy_timeout=30000');print('ok')"

然后写操作收拢到一个进程 其余走队列

python writer.py --queue chroma-queue --workers 1

多进程场景换 HttpClient 独立起服务

docker run -p 8000:8000 -v ${PWD}/chroma:/chroma/chroma chromadb/chroma:0.5.5

排查用的命令都是临时敲的,没有写成脚本,事后才整理。

手上没有现成的复现脚本,就照着线上请求手工拼了一个。

改完先别撤,确认这几项。两个进程交替写入 2000 条后 count 与输入一致,日志里不再出现 database is locked。

提醒一点。PersistentClient 只适合单进程,多副本或多进程要换 HttpClient,否则网络盘上还会出现更隐蔽的锁失效。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189