首页 > mongodb使用find查询获取的游标是否可以遍历出查询执行后的数据库新增的记录

mongodb使用find查询获取的游标是否可以遍历出查询执行后的数据库新增的记录

mongodb使用find查询返回的游标,是否可以遍历出查询执行后(记录比较多查询时间比较长,此时查询还未执行完)数据表新增的记录。
例如:
线程A在时间点t1使用find查询数据表user返回游标,遍历数据记录。
线程B在时间点t2使用insert向数据表user插入记录。
线程B在时间点t3执行完成。
线程A在时间点t4执行完成。
时间:t1 < t2 < t3 < t4
问:线程A是否可以查询到线程B新增的记录?


这是个非常好的问题,简单说 MongoDB 不保证结果是否包含新文档,因为它涉及到多个文档,甚至包括未来可能插入的文档。在传统数据库中,可能读到新插入的值,这一异常情况被称作 Phantom (幽灵),能满足这一点的 isolation (隔离、独立) 级别是最高的 serializable (可串行化),就是说例子中的一读一写两组操作看起来好像是一先一后。用锁机制实现的代价也非常高,性能也就比较差。参见这一论文。回到 MongoDB, MongoDB 以文档为单元,能够保证文档级别的隔离,但是不保证多文档间的操作的隔离(独立),也就不支持事务,换来的是高性能。

@huandu 说的没错,你测试时用 find().batchSize(2) 改成每批次读2个文档,就会发现是可以读到新加入的文档的。默认的 batchSize 在 shell 里是 20,可能就不容易观察到了。别用 batchSize(1), 因为历史原因它等于limit()。


不一定。

mongodb cursor 没有隔离,可能会返回更新后的数据。

不过实际尝试过程中发现,无论如何 insert,cursor 始终无法返回新插入的数据。这可能是 mongodb 的实现细节,也可能在某些特殊情况下 cursor 才可以访问到新 insert 的数据,总之没有文档支持,不应该依赖这个行为。

【热门文章】
【热门文章】