2016-02-19 76 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)的完全重新啓動對於我的錯誤消息最終消失是必要的。首先這可能是值得嘗試的。