MongoDB,复制和错误:{"$err":"NOT MASTER AND SLAVEOK=FALSE","代码": 13435 }

我第一次尝试了Mongo复制集。

我在EC2上使用Ubuntu,启动了三个实例。 我使用了每个实例的私有IP地址。我选择作为主要的,下面是代码。

mongo --host Private IP Address
rs.initiate()
rs.add(“Private IP Address”)
rs.addArb(“Private IP Address”)

在这一点上一切都很好。当我转到http://ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com:28017/_replset站点时,我看到我有一个主服务器、一个辅助服务器和一个仲裁服务器。

好了,现在来做个测试。

在Primary上创建一个数据库,代码如下:

use tt
db.tt.save( { a : 123 } )

然后,我在辅助服务器上执行此操作,并得到以下错误:

db.tt.find()
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

我对MongoDB和复制很陌生,但我认为如果我在一个数据库中做了什么,它就会转到另一个数据库中。那么,如果我在其中添加一条记录,我需要做什么才能跨机器复制呢?

190388 次浏览

You have to set "secondary okay" mode to let the mongo shell know that you're allowing reads from a secondary. This is to protect you and your applications from performing eventually consistent reads by accident. You can do this in the shell with:

rs.secondaryOk()

After that you can query normally from secondaries.

A note about "eventual consistency": under normal circumstances, replica set secondaries have all the same data as primaries within a second or less. Under very high load, data that you've written to the primary may take a while to replicate to the secondaries. This is known as "replica lag", and reading from a lagging secondary is known as an "eventually consistent" read, because, while the newly written data will show up at some point (barring network failures, etc), it may not be immediately available.

Edit: You only need to set secondaryOk when querying from secondaries, and only once per session.

in mongodb2.0

you should type

rs.slaveOk()

in secondary mongod node

To avoid typing rs.slaveOk() every time, do this:

Create a file named replStart.js, containing one line: rs.slaveOk()

Then include --shell replStart.js when you launch the Mongo shell. Of course, if you're connecting locally to a single instance, this doesn't save any typing.

THIS IS JUST A NOTE FOR ANYONE DEALING WITH THIS PROBLEM USING THE RUBY DRIVER

I had this same problem when using the Ruby Gem.

To set slaveOk in Ruby, you just pass it as an argument when you create the client like this:

mongo_client = MongoClient.new("localhost", 27017, { slave_ok: true })

https://github.com/mongodb/mongo-ruby-driver/wiki/Tutorial#making-a-connection

mongo_client = MongoClient.new # (optional host/port args)

Notice that 'args' is the third optional argument.

I am just adding this answer for an awkward situation from DB provider.

what happened in our case is the primary and secondary db shifted reversely (primary to secondary and vice versa) and we are getting the same error.

so please check in the configuration settings for database status which may help you.

slaveOk does not work anymore. One needs to use readPreference https://docs.mongodb.com/v3.0/reference/read-preference/#primaryPreferred

e.g.

const client = new MongoClient(mongoURL + "?readPreference=primaryPreferred", { useUnifiedTopology: true, useNewUrlParser: true });

I got here searching for the same error, but from Node.js native driver. The answer for me was combination of answers by campeterson and Prabhat.

The issue is that readPreference setting defaults to primary, which then somehow leads to the confusing slaveOk error. My problem is that I just wan to read from my replica set from any node. I don't even connect to it as to replicaset. I just connect to any node to read from it.

Setting readPreference to primaryPreferred (or better to the ReadPreference.PRIMARY_PREFERRED constant) solved it for me. Just pass it as an option to MongoClient.connect() or to client.db() or to any find(), aggregate() or other function.

const { MongoClient, ReadPreference } = require('mongodb');
const client = await MongoClient.connect(MONGODB_CONNECTIONSTRING, { readPreference: ReadPreference.PRIMARY_PREFERRED });

WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead. rs.secondaryOk()

Adding readPreference as PRIMARY

const { MongoClient, ReadPreference } = require('mongodb');
const client = new MongoClient(url, { readPreference: ReadPreference.PRIMARY_PREFERRED});
client.connect();