问题
I'm trying to build a nagios check to check for how long a mongoDB has been locked using fsyncLock() for backup purposes (if the iSCSI snapshotting script blows up and the mongo is not being unlocked for example)
I was thinking about using a simple
$currentLock->run_command({currentOp => 1})
$isLocked = $currentLock->{fsyncLock}
But it seems like run_command() doesn't support currentOp yet. (As seen in there: https://github.com/MLstate/opalang/blob/master/lib/stdlib/apis/mongo/commands.opa)
Woudl anybody have an advice on how to check if a mongo is locked with a perl script? If not, I guess I'll go for some bash. I was thinking about using a db.eval('db.currentOp()') but I'm getting a bit lost.
Thanks!
回答1:
You are right that run_command
does not support doing a currentOp
directly. However, if we look at the implementation of db.currentOp
in the mongo
shell, we can see how it works under the hood:
> db.currentOp
function (arg) {
var q = {};
if (arg) {
if (typeof arg == "object") {
Object.extend(q, arg);
} else if (arg) {
q.$all = true;
}
}
return this.$cmd.sys.inprog.findOne(q);
}
So we can query the special collection $cmd.sys.inprog
on the Perl side to get the same inprog
array that would be returned in the shell.
use strict;
use warnings;
use MongoDB;
my $db = MongoDB::MongoClient->new->get_database( 'test' );
my $current_op = $db->get_collection( '$cmd.sys.inprog' )->find_one;
When the server is not locked, it will return a structure in $current_op
that looks something like this:
{
'inprog' => [
{
'connectionId' => 53,
'insert' => {},
'active' => bless( do{\(my $o = 0)}, 'boolean' ),
'lockStats' => {
'timeAcquiringMicros' => {
'w' => 1,
'r' => 0
},
'timeLockedMicros' => {
'w' => 9,
'r' => 0
}
},
'numYields' => 0,
'locks' => {
'^' => 'w',
'^test' => 'W'
},
'waitingForLock' => $VAR1->{'inprog'}[0]{'active'},
'ns' => 'test.fnoof',
'client' => '127.0.0.1:50186',
'threadId' => '0x105a81000',
'desc' => 'conn53',
'opid' => 7152352,
'op' => 'insert'
}
]
};
During an fsyncLock()
, you'll get an empty inprog
array but you will have a helpful info
field and the expected fsyncLock
boolean:
{
'info' => 'use db.fsyncUnlock() to terminate the fsync write/snapshot lock',
'fsyncLock' => bless( do{\(my $o = 1)}, 'boolean' ), # <--- that's true
'inprog' => []
};
So, putting it all together, we get:
use strict;
use warnings;
use MongoDB;
my $db = MongoDB::MongoClient->new->get_database( 'fnarf' );
my $current_op = $db->get_collection( '$cmd.sys.inprog' )->find_one;
if ( $current_op->{fsyncLock} ) {
print "fsync lock is currently ON\n";
} else {
print "fsync lock is currently OFF\n";
}
回答2:
I actually decided to switch for a solution in bash (easier for what I want to do with the data later):
currentOp=`mongo --port $port --host $host --eval "printjson(db.currentOp())"`
Then some sort of grep -Po '"fsyncLock" : \d'
Thanks for the Perl insight though, it worked perfectly
来源:https://stackoverflow.com/questions/14763773/grab-the-fsynclock-status-of-a-mongo-db-in-perl