PHP 5.2.13 MongoCursorException'重复键错误索引'

时间:2011-06-30 22:36:48

标签: php mongodb

在将文档插入我们的mongo数据库时,我得到重复的_ids。这是一个间歇性问题,只在某些负载下发生(可以通过某些测试脚本重现)。

这是一些测试代码,所以你不认为我试图双重插入同一个对象(我知道PHP mongo驱动程序添加了_id字段):

// Insert a job
$job = array(
    'type'      =>  'cleanup',
    'meta'      =>  'cleaning the data',
    'user_id'   =>  new MongoId($user_id),
    'created'   =>  time(),
    'status'    =>  'pending'
);
$this->db->job->insert($job, array('safe' => true));      // <-- failz here

我疯狂地安装了最新的稳定(1.1.4)mongo驱动程序无济于事。这不是重负荷。我们在一台服务器上执行的操作可能是5 req / s,因此inc值的16M rec / s限制可能不是问题。

任何想法都将不胜感激。我希望有人在某处使用mongo和PHP并插入超过5个docs / s并且遇到了这个问题;)。

CNC中
在CentOS 5.4 x86_64,linux 2.6.18-164.el5xen,Apache worker 2.2.15,PHP 5.2.13,MongoDB 1.8.1

-EDIT2-
正如评论中所述,我现在使用最新版本的PECL驱动程序(1.2.0),问题仍然存在。

-EDIT3-
忘了发布确切的错误:

Uncaught exception 'MongoCursorException' with message 'E11000 duplicate key error index: hannibal.job.$_id_ dup key

2 个答案:

答案 0 :(得分:1)

对此有一个不同的解决方案(预制棒/工人MPM在我的情况下没有帮助,我们以prefork的形式运行,无论如何都是默认的。)

问题是插入数组是通过引用传递的,并由PHP MongoDB库修改以包含ID。您需要清除ID。

想象一下下面的代码:

$aToInsert = array('field'=>$val1);
$collection->insert($aToInsert);   << This will have '_id' added
$aToInsert['field'] = $val2
$collection->insert($aToInsert);  << This will fail with the above error

为什么呢?该库会发生什么:

$aToInsert = array('field'=>$val1);
$collection->insert($aToInsert);

// $aToInsert has '_id' added by PHP MongoDB library
// Therefore $aToInsert = array('field'=>$val1, '_id'=>MongoID() );

$aToInsert['field'] = $val2
// Therefore $aToInsert = array('field'=>$val2, '_id'=>MongoID() );

$collection->insert($aToInsert);
// This will not add '_id' as it already exists. But will now fail.

解决方案是重新初始化数组

$aToInsert = array('field'=>$val1);
$collection->insert($aToInsert);
$aToInsert = array('field'=>$val2);
$collection->insert($aToInsert);

或取消设置ID

$aToInsert = array('field'=>$val1);
$collection->insert($aToInsert);
unset($aToInsert['_id']);
$aToInsert['field'] = $val2
$collection->insert($aToInsert);  << This will now work

答案 1 :(得分:0)

看起来它与安装的Apache版本(worker)有关。安装apache prefork之后,我们发现服务器上没有更多重复的_id错误。

我的猜测是这与Mongo驱动程序使用的全局计数器有关。我认为线程之间缺乏通信可能是原因...也许一个池有每个线程的实例计数器,但由于PID是相同的,你会遇到冲突。

我不知道内部,但这似乎是最可能的解释。不要将Apache Worker MPM与PHP MongoDB驱动程序一起使用。如果不是这样,或者您知道修复,请发表评论并纠正我。