插入文档后,立即从MongoDB集合中检索文档时遇到问题。我正在创建文档,然后运行一个查询(无法提前确定)以获取集合中所有文档的子集。问题是我插入的部分或全部文档没有包含在结果中。
过程是:
- 查找最近记录的时间戳
- 查找自那时以来发生的交易
- 为这些事务生成记录,每个事务生成
insert()
(这可以而且将成为单个大容量插入) find()
一些记录
文档总是写得很成功,但在运行find()
时,通常不会包含新文档。几秒钟后即可使用。
我相信,当我尝试检索新文档时,它们还没有传播到副本集的所有成员,尽管我怀疑情况可能并非如此,因为我使用的是与insert()
和find()
相同的连接。
我相信这可以通过写问题来解决,但我不确定指定什么值来确保文档已传播到副本集的所有成员,或者至少传播到将用于find()
操作的成员(如果可以提前知道的话)。
我不想硬编码成员总数,因为当添加另一个成员时,这会中断。insert()
操作是否缓慢并不重要。
读取首选项
当您向集合写入时,最好将readPreference
设置为"primary",以确保您从与您写入的MongoDB服务器相同的服务器上进行读取。
您可以使用MongoCollection::setReadPreference()
方法来完成此操作。
$db->mycollection->setReadPreference(MongoClient::RP_PRIMARY);
$db->mycollection->insert(['foo' => 'bar']);
$result = $db->mycollection->find([]);
写下担忧(不要这样做!)
您可能会倾向于使用写问题来等待通过使用w=3
(对于3服务器设置)将数据复制到所有辅助设备。然而,这不是要走的路。
MongoDB复制的一个好处是可以自动进行故障切换。在这种情况下,您可能只有不到3台服务器可以接受数据,这会导致脚本永远等待。
没有w=all
可以写入所有已启动的服务器。使用这样的书面关注是不好的。一个刚刚从故障转移中恢复过来的中学可能会落后几个小时,需要很长时间才能赶上。您的脚本将等待(挂起),直到所有的辅助进程都被占用。
一个好的做法是never在管理任务之外将w=N
与N > majority
一起使用。
基本上,您正在寻找一个写问题,它(用Layman的术语)允许您指定插入何时完成。
在PHP中,这是通过在insert语句中提供一个选项来完成的,因此您需要类似的东西
w=N个副本集已确认写入将由主服务器确认,并复制到N-1个辅助服务器。
或者如果您不想硬编码N
:
w=副本集标记集已确认写入由整个标签集的成员确认
$collection->insert($someDoc, ["w" => 3]);