Hi Michael!
1) You can set the 'slaveOk()' property on the Mongo object within your code. You can either apply it to the Mongo object, or to a DBCollection Object.
Ref:
-
http://api.mongodb.org/java/current/com/mongodb/Mongo.html#slaveOk%28%29 -
http://api.mongodb.org/java/current/com/mongodb/DBCollection.html#slaveOk%28%292) Can you post some sample output from 'mongostat' while the slowdown is happening? It would also help if you can post the output of db.currentOp() from the shell during the slowdown, as that might give a hint as to what is the blocking operation.
3) Is the 'refDate' columned indexed? If not, that could be the cause of your problem.
What is the output of db.find({$or':[{'refDate':null}, {'refDate':{$lt, ISO_Date(....)}}]}).explain() ?
4) 95% lock percentage is not OK. At that level, you'll get reader starvation. This is the most likely cause of the slowdown you're seeing.
5) If you're doing multiple inserts/updates in a loop, then you can slow down the write operations in order to to get better read performance. There are two ways to do this.
- You can insert some sleep() operations between the writes in order to allow the queued readers time to satisfy their requests.
- You can insert some getLastError() commands into your stream of inserts and updates, using a WriteConcern of REPLICAS_SAFE.
Using the WriteConcern is arguably the more elegant way to do this. It will cause MongoDB to not allow the next write operation to go forward until the write has propagated to at least one secondary before the write call returns. Doing this will cause the next write to block for a while, thus allowing the waiting readers to come in.
You would only want to do this once every thousand write operations or so, since specifying REPLICAS_SAFE will severely impact performance.
6) If the operation that's causing the slowdown is a single massive update() command, then the techniques described in (4) above won't work for you. If that's the case, then you may need to restructure your update to do less work in one unit in order to allow the readers to proceed.
You may have to break up your update into multiple smaller updates. For example, if you're updating everything in the last 24 hours, you might have to restructure your update to update one hour's worth of data at a time.
Please let me know if you have further questions.
-William
On Friday, August 3, 2012 2:39:56 AM UTC-7, Michael Illgner wrote:
Thanks for the answers
Our update/insert loop takes abount 20min, the interesting point ist
that most of the 'timeouts' occur in the first 1-2 minutes of the
process, after that everything is fine.
At last we have a kind of cleanup command to expire some 'old' date
update({'$or':[{'refDate':null}, {'refDate':{$lt, ISO_Date(....)}}]}, {'$set': {'status':0}})
this command runs about 5min and during its execution we have some more time, mongostatshows that the global lock ist about 95%, which seems to be OK, because this command affects most of the data,
for the slaveOK parameter
Both write and update application should use the same MongoURI pointing to the same router/mongos process, but the 'reader' should append slaveOK=true to the uri ?
BTW
We are using the java driver 2.8