不断变化的MONGODB结果集

在前几天的一次php+mongoDB数据库实做中,遇到了一个很奇怪的问题:

有N张collection,每个collection中有Mn条记录,我先循环N,去每张collection中find()到所有记录,然后在针对每条记录做update()操作,

$mo = new Mongo();

$db =  $mo->dbname;

for($i=0;$i<100;$i++){

$coll = $db->selectCollection(’col’.$i){

$cursor = $coll->find();

while($cursor as $k=>$v){

$uid = $v['uid'];

$rs = $coll->update(array(’uid’=>$uid),array(要更新的内容));

}

}

}

但是实际上,有些记录被update的两次,百思不得其解,update()的$option换了所有方式,都无效。

后来,在Sam的帮助下,详细查了php手册的mongoDB一段,最后发现:

http://www.php.net/manual/en/mongocursor.snapshot.php

MongoCursor MongoCursor::snapshot()

Use snapshot mode for the query. Snapshot mode assures no duplicates are returned, or objects missed, which were present at both the start and end of the query’s execution (if an object is new during the query, or deleted during the query, it may or may not be returned, even with snapshot mode).
Note that short query responses (less than 1MB) are always effectively snapshotted.
Currently, snapshot mode may not be used with sorting or explicit hints.

大意是:$cursor->snapshot();之后,再插入或者删除符合条件的记录时,获取的结果集将不再变化。如果是小于1M的结果集会自动被当作snapshot来处理。

结论:

1,如果你想或的固定的结果集,那么在find()之后要snapshot()一下,保证一致性。

2,不管是否小于1M,这一点在我们开发的时候可能不好评估,所以,只要是要固定结果集的,都snapshot好了。

疑问:

1,怀疑这是bug,因为在说明中并没有提到update操作会影响结果集,而只提到了删除和添加对结果集的影响。因为我update的时候并没有增加记录。

2,为什么不是一直影响下去?如果我获得一个结果集,然后在循环过程中做update,那应该就成了个周而复始的循环才对。而我测试的结果是,循环的次数并不是记录数量的两倍,而是不确定次数的循环。

 

 

这个应该不是bug,《mongodb权威指南》P62页 “获取一致结果” 里有描述。 不一致只在游标等待结果时集合内容被改变的情况下发生。