MongoDB replica set preventing queries to secondary

Ryan Kennedy picture Ryan Kennedy · Jun 17, 2013 · Viewed 47.4k times · Source

To set up the replica set, I've run in 3 separate terminal tabs:

 $ sudo mongod --replSet rs0 --dbpath /data/mining --port 27017
 $ sudo mongod --replSet rs0 --dbpath /data/mining2 --port 27018
 $ sudo mongod --replSet rs0 --dbpath /data/mining3 --port 27019

Then, I configured replication in the Mongo shell and verified that it worked:

 > var rsconf = {
     _id: "rs0",
     members: [
       {
         _id: 0,
         host: 'localhost:27017'
       },
       {
         _id: 1,
         host: 'localhost:27018'
       },
       {
         _id: 2,
         host: 'localhost:27019'
       }
     ]
   };
 > rs.initiate(rsconf);
{
  "info": "Config now saved locally.  Should come online in about a minute.",
  "ok": 1
}
// Some time later...
 > rs.status()
{
  "set": "rs0",
  "date": ISODate("2013-06-17T13:23:45-0400"),
  "myState": 2,
  "syncingTo": "localhost:27017",
  "members": [
    {
      "_id": 0,
      "name": "localhost:27017",
      "health": 1,
      "state": 1,
      "stateStr": "PRIMARY",
      "uptime": 4582,
      "optime": {
        "t": 1371489546,
        "i": 1
      },
      "optimeDate": ISODate("2013-06-17T13:19:06-0400"),
      "lastHeartbeat": ISODate("2013-06-17T13:23:44-0400"),
      "lastHeartbeatRecv": ISODate("2013-06-17T13:23:44-0400"),
      "pingMs": 0
    },
    {
      "_id": 1,
      "name": "localhost:27018",
      "health": 1,
      "state": 2,
      "stateStr": "SECONDARY",
      "uptime": 5034,
      "optime": {
        "t": 1371489546,
        "i": 1
      },
      "optimeDate": ISODate("2013-06-17T13:19:06-0400"),
      "self": true
    },
    {
      "_id": 2,
      "name": "localhost:27019",
      "health": 1,
      "state": 2,
      "stateStr": "SECONDARY",
      "uptime": 4582,
      "optime": {
        "t": 1371489546,
        "i": 1
      },
      "optimeDate": ISODate("2013-06-17T13:19:06-0400"),
      "lastHeartbeat": ISODate("2013-06-17T13:23:44-0400"),
      "lastHeartbeatRecv": ISODate("2013-06-17T13:23:45-0400"),
      "pingMs": 0,
      "syncingTo": "localhost:27017"
    }
  ],
  "ok": 1
}

My script runs fine against the primary:

 $ ./runScripts.sh -h localhost -p 27017
MongoDB shell version: 2.4.3
connecting to: localhost:27017/test
Successful completion

However, against either secondary:

 $ ./runScripts.sh -h localhost -p 27018
MongoDB shell version: 2.4.3
connecting to: localhost:27017/test
Mon Jun 17 13:30:22.989 JavaScript execution failed: count failed: 
{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" } 
at src/mongo/shell/query.js:L180
failed to load: /.../.../myAggregateScript.js

I've read in multiple places to use rs.slaveOk() or db.getMongo().setSlaveOk(), but neither of these had any effect, whether entered from the shell or called in my script. These statements did not throw errors when called, but they didn't fix the problem, either.

Does anyone know why I can't configure my replset to allow querying of the secondary?

Answer

James Wahlin picture James Wahlin · Jun 17, 2013

rs.slaveOk() run in the mongo shell will allow you to read from secondaries. Here is a demonstration using the mongo shell under MongoDB 2.4.3:

$ mongo --port 27017
MongoDB shell version: 2.4.3
connecting to: 127.0.0.1:27017/test
replset:PRIMARY> db.foo.save({})
replset:PRIMARY> db.foo.find()
{ "_id" : ObjectId("51bf5dbd473d5e80fc095b17") }
replset:PRIMARY> exit

$ mongo --port 27018
MongoDB shell version: 2.4.3
connecting to: 127.0.0.1:27018/test
replset:SECONDARY> db.foo.find()
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
replset:SECONDARY> rs.slaveOk()
replset:SECONDARY> db.foo.find()
{ "_id" : ObjectId("51bf5dbd473d5e80fc095b17") }
replset:SECONDARY> db.foo.count()
1