38

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?

Ryan Kennedy
  • 3,275
  • 4
  • 30
  • 47
  • 1
    rs.slaveOk() should allow you to read. I just tested using the mongo shell and 2.4.3 and a count() worked for me. Can you share your script? – James Wahlin Jun 17 '13 at 19:07
  • @JamesWahlin is right - the only way this is happening is if you didn't set rs.slaveOk() before running the command that gave this output. More information about your js script contents may help. – Asya Kamsky Jun 17 '13 at 19:38
  • 2
    possible duplicate of [mongodb, replicates and error: { "$err" : "not master and slaveOk=false", "code" : 13435 }](http://stackoverflow.com/questions/8990158/mongodb-replicates-and-error-err-not-master-and-slaveok-false-code) – Pykler Jul 25 '14 at 16:26

3 Answers3

84

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
Xolve
  • 22,298
  • 21
  • 77
  • 125
James Wahlin
  • 2,811
  • 21
  • 22
  • 3
    There are reasons that `slaveOK` exists, it would be worth while pointing out what those reasons are. For example: `IMPORTANT Exercise care when specifying read preferences: Modes other than primary may return stale data because with asynchronous replication, data in the secondary may not reflect the most recent write operations.` – Madbreaks Feb 17 '17 at 17:37
  • Duhhh I was connected on 27017 which was my primary.... after a reboot I had to rebuild the stupid thing, and my new master was 27018. The post above helped. – Andy May 17 '17 at 13:18
  • 5
    Just for info: `rs.slaveOk()` is a per connection setting. Each connection must issue this this command before trying to interact with the databases. – Daniel F Jan 15 '18 at 17:33
21

You have to run the command rs.slaveOk() in the secondary server's shell.

CJBS
  • 15,147
  • 6
  • 86
  • 135
Dung Nguyen
  • 311
  • 2
  • 5
0

Use the following to run queries on your MongoDB secondary:

db.getMongo().setReadPref('secondary') 
Dror
  • 5,107
  • 3
  • 27
  • 45