Compacting secondary blocking php query with php driver 1.2.9

27 views
Skip to first unread message

john

unread,
Mar 9, 2012, 4:23:40 PM3/9/12
to mongodb-user
MongoDB 2.03 with php driver 1.2.9

A simple three nodes replicaSet: primary, secondary, and arbitor

To reproduce: start a simple php daemon like -
$mongo_connection = new Mongo("mongodb://localhost:27017, localhost:
27018", array("replicaSet" => "test"));
$db = $mongo_connection->selectDB( "bookstore" );
$collection = $db->selectCollection( "values" );
$collection->setSlaveOkay(true);
while (true) {
try {
$obj = $collection->find()->limit(5);

foreach($obj as $next)
{
print $next['stock_symbol']."\n";
$docs[] = array('stock_id' => $next['stock_symbol']);
}
print time()."\n\n";
}
catch(MongoCursorException $e) {
echo 'Mongo threw an exception at '.time().' code: '.$e-
>getCode().' message: '.$e->getMessage().'\n';
}
}

then run compact on the secondary localhost:27018/bookstore. I can see
the php query is being blocked. When I restart the script, it works
again.

let me know if there's any solution.

John

Kyle Banker

unread,
Mar 9, 2012, 6:03:05 PM3/9/12
to mongodb-user
You're setting setSlaveOk. This means that the query is being sent to
the secondary node. But compact blocks all queries. So this is
expected behavior. If you don't want the script to be blocked, don't
set slave ok.

john

unread,
Mar 9, 2012, 6:20:11 PM3/9/12
to mongodb-user
I thought the correct behavior should be -
if a slaveOk read is requested, that read query will go to a SECONDARY
server if one is available; only if none are available will it go to
the PRIMARY.

In my case, one secondary is in recovery, no more secondary available,
only the primary is available, it should read from primary unless I'm
wrong.

John

Kyle Banker

unread,
Mar 14, 2012, 4:33:41 PM3/14/12
to mongodb-user
The problem is that the php driver doesn't check the state of the
replica set before sending the query. And since a query takes a read
lock, it's going to queue up behind the write lock that the compact
command has taken. So the blocking is expected. It may be worthwhile
to open a server case which causes the query to be rejected right away
if compact is running.

In any case, the best temporary solution is not to send queries to the
secondary node while it's being compacted.

On Mar 9, 7:20 pm, john <dr.john...@gmail.com> wrote:
> I thought the correct behavior should be -
> if a slaveOk read is requested, that read query will go to a SECONDARY
> server if one is available; only if none are available will it go to
> the PRIMARY.
>
> In my case, one secondary is in recovery, no more secondary available,
> only the primary is available, it should read from primary unless I'm
> wrong.
>
> John
>
> On Mar 9, 5:03 pm, Kyle Banker <kyleban...@gmail.com> wrote:
>
>
>
>
>
>
>
> > You're setting setSlaveOk. This means that the query is being sent to
> > the secondary node. Butcompactblocks all queries. So this is
> > expected behavior. If you don't want the script to be blocked, don't
> > set slave ok.
>
> > On Mar 9, 4:23 pm, john <dr.john...@gmail.com> wrote:
>
> > > MongoDB 2.03 withphpdriver 1.2.9
>
> > > A simple three nodes replicaSet: primary, secondary, and arbitor
>
> > > To reproduce: start a simplephpdaemon like -
> > > $mongo_connection = new Mongo("mongodb://localhost:27017, localhost:
> > > 27018", array("replicaSet" => "test"));
> > > $db = $mongo_connection->selectDB( "bookstore" );
> > > $collection = $db->selectCollection( "values" );
> > > $collection->setSlaveOkay(true);
> > > while (true) {
> > >         try {
> > >             $obj = $collection->find()->limit(5);
>
> > >             foreach($obj as $next)
> > >             {
> > >               print $next['stock_symbol']."\n";
> > >               $docs[] = array('stock_id' => $next['stock_symbol']);
> > >             }
> > >             print time()."\n\n";
> > >     }
> > >     catch(MongoCursorException $e) {
> > >            echo 'Mongo threw an exception at '.time().' code: '.$e-
>
> > > >getCode().' message: '.$e->getMessage().'\n';
> > >    }
> > > }
>
> > > then runcompacton the secondary localhost:27018/bookstore. I can see
> > > thephpquery is being blocked. When I restart the script, it works

Kyle Banker

unread,
Mar 14, 2012, 4:35:27 PM3/14/12
to mongodb-user
I've opened a feature request on your behalf:
https://jira.mongodb.org/browse/SERVER-5318

On Mar 9, 7:20 pm, john <dr.john...@gmail.com> wrote:
> I thought the correct behavior should be -
> if a slaveOk read is requested, that read query will go to a SECONDARY
> server if one is available; only if none are available will it go to
> the PRIMARY.
>
> In my case, one secondary is in recovery, no more secondary available,
> only the primary is available, it should read from primary unless I'm
> wrong.
>
> John
>
> On Mar 9, 5:03 pm, Kyle Banker <kyleban...@gmail.com> wrote:
>
>
>
>
>
>
>
> > You're setting setSlaveOk. This means that the query is being sent to
> > the secondary node. Butcompactblocks all queries. So this is
> > expected behavior. If you don't want the script to be blocked, don't
> > set slave ok.
>
> > On Mar 9, 4:23 pm, john <dr.john...@gmail.com> wrote:
>
> > > MongoDB 2.03 withphpdriver 1.2.9
>
> > > A simple three nodes replicaSet: primary, secondary, and arbitor
>
> > > To reproduce: start a simplephpdaemon like -
> > > $mongo_connection = new Mongo("mongodb://localhost:27017, localhost:
> > > 27018", array("replicaSet" => "test"));
> > > $db = $mongo_connection->selectDB( "bookstore" );
> > > $collection = $db->selectCollection( "values" );
> > > $collection->setSlaveOkay(true);
> > > while (true) {
> > >         try {
> > >             $obj = $collection->find()->limit(5);
>
> > >             foreach($obj as $next)
> > >             {
> > >               print $next['stock_symbol']."\n";
> > >               $docs[] = array('stock_id' => $next['stock_symbol']);
> > >             }
> > >             print time()."\n\n";
> > >     }
> > >     catch(MongoCursorException $e) {
> > >            echo 'Mongo threw an exception at '.time().' code: '.$e-
>
> > > >getCode().' message: '.$e->getMessage().'\n';
> > >    }
> > > }
>
> > > then runcompacton the secondary localhost:27018/bookstore. I can see
> > > thephpquery is being blocked. When I restart the script, it works
Reply all
Reply to author
Forward
0 new messages