2016-02-19 74 views
1

我在使用PHP脚本尝试浏览我的一个集合中的所有文档时遇到问题。该集合有大约500k个文档。数据库正在运行在Ubuntu 14.04上运行的Mongo 2.6.9。我使用这个语法搜索collecton:文档长度不等于缓冲区

$mongo = new MongoClient("mongodb://192.168.2.2:27017,192.168.2.3:27017/products?replicaSet=preplset"); 
$products = $mongo->products->content; 
$cursor = $products->find(); 
while($cursor->hasNext() !== false) { 
    echo "some information"; 
} 

我收到以下错误消息(堆转储):

object(MongoCursorException)#24 (8) { 
    ["message":protected]=> string(61) "Document length (74 bytes) is not equal to buffer (219 bytes)" 
    ["string":"Exception":private]=> string(0) "" 
    ["code":protected]=> int(42) 
    ["file":protected]=> string(41) "...script.php" 
    ["line":protected]=> int(29) 
    ["trace":"Exception":private]=> 
    array(1) { 
     [0]=> array(6) { 
      ["file"]=> string(41) "...value.php" 
      ["line"]=> int(29) 
      ["function"]=> string(7) "getNext" 
      ["class"]=> string(11) "MongoCursor" 
      ["type"]=> string(2) "->" 
      ["args"]=> array(0) {} 
     } 
    } 
    ["previous":"Exception":private]=> NULL 
    ["host":"MongoCursorException":private]=> NULL 
} 

长度变化。我看到了十几种不同的长度。每次运行此脚本时,它都会获得不同百分比的集合。有时它会在4k文件之后抛出这个异常,有时候是180k。我确定我在任何时候都对系列进行了更改,它是一个正在不断更新的生产数据库

+0

对于临时性的问题,我很高兴看到一种方法来捕获异常并处理它。我有一个try/catch块,但这个异常导致我的脚本退出。 – JohnGalt

回答

0

对于将来可能有此问题的任何人,我将发布我认定为的我的问题的原因以及我为解决问题所采取的步骤。

首先,最后重新启动我的mongodb服务器,一次解决我的问题。如果您正在运行功能复制集,那么可能首先需要尝试(在我下面概述的所有工作之前)。

该问题是由某人在复制集的PRIMARY节点上创建索引而未明确指示要在后台创建索引(这是有问题的)而创建的。然后我用“背景”选项设置了各种索引(不是问题的一部分)。当我开始得到这个错误信息时,我删除了所有的索引,但是它们仍然保留在内存中(甚至可能在PRIMARY --unverified文件锁定中)。

要解决这个问题,我把每个成员(一一)下线,并给他们带来了在线上的另一个(随机)端口(这样他们就不会与集通讯):

sudo mongod --port 44444 --dbpath /path/to/mongodb/files/ #default is /data/db 

(中路径是需要的,因为我的地址在非默认位置)

一旦每个服务器都自行加载,我删除了所有索引并重新创建了我真正想要的那些(然后重新索引以确保它们是干净的):

db.collection.dropIndexes() #this drops all indexes except _id index 
db.collection.createIndex({ *indexfield*: 1 }) #1 or -1 for ASC or DESC 
db.collection.reIndex() #probably not necessary 

然后,我退出了mongodb服务并在正常情况下重新启动它,以便它再次成为副本集的一部分。

这些步骤应该足以解决问题,但我发现每个节点(特别是PRIMARY)的完全重新启动对于我的错误消息最终消失是必要的。首先这可能是值得尝试的。