并发、锁定和版本控制

并发性

这个 FileIndex 对象是“无状态的”,应该可以在线程之间共享。

A Reader 对象(位于 Searcher 对象)包装打开的文件,通常单个方法依赖于一致的文件光标位置(例如,它们有两个 file.read() 如果另一个线程在两个read调用之间移动光标,就会发生坏事情)。您应该在代码中每个线程使用一个读卡器/搜索器。

读卡器/搜索者倾向于缓存信息(例如用于排序的字段缓存),因此如果您可以在多个搜索请求之间共享一个信息,这将是一个巨大的性能胜利。

锁定

一次只能有一个线程/进程写入索引。当您打开一个编写器时,它会锁定索引。如果试图在另一个线程/进程中打开同一索引上的写入程序,它将引发 whoosh.store.LockError .

在多线程或多进程环境中,您的代码需要注意,如果编写器已打开,则打开编写器可能会引发此异常。whoosh包括几个示例实现( whoosh.writing.AsyncWriterwhoosh.writing.BufferedWriter )解决写锁问题的方法。

在编写器打开和提交期间, 索引仍可以读取. Existing readers are unaffected and new readers can open the current index normally.

锁定文件

锁定索引是通过获取 <indexname>_WRITELOCK 索引目录中的文件。释放文件锁后不会删除该文件,因此该文件存在 does not 表示索引已锁定。

版本

打开读卡器/搜索器时,读卡器表示 current version 索引的如果有人将更改写入索引,则任何已打开的读卡器 will not 自动选取更改。读卡器总是在读卡器打开时看到索引的存在。

如果在多个搜索请求中重新使用搜索者,可以使用 whoosh.searching.Searcher.up_to_date() . 如果搜索者不是最新的,可以使用 whoosh.searching.Searcher.refresh() ::

# If 'searcher' is not up-to-date, replace it
searcher = searcher.refresh()

(如果搜索者有最新版本的索引, refresh() 只需返回即可。)

调用 Searcher.refresh() 更有效的方法是关闭搜索者并打开一个新的搜索者,因为它将重新使用任何未更改的底层读卡器和缓存。