在DBA的日常工作中,数据库的会话监控和管理是一项十分重要的工作,在关系型数据库中,有v$session、processlist、pg_stat_activity等表或者视图提供会话信息查询,但是在非关系型的mongodb中,除了local库的system.session集合中存了简单的用户信息外,并无其他集合存了会话信息,只能通过db.currentOp()命令来采集信息。
db.currentOp()输出的结果如下:
由上图可看出输出结果inprog是一个数组,在数组里面要实现统计和过滤等,比较困难,只能结合javascript脚本实现。而在Mongodb3.6中引入了$currentop聚合管道符,使Mongodb的会话管理变得更加容易。
该管道符只能在admin库执行,使用方法:
{$currentOp: { allUsers: <boolean>, idleConnections: <boolean>} }。
示例:显示当前会话,按照客户端IP进行分组统计
--显示当前的会话中,以客户端IP(10网段)地址分组统计连接数
useadmin db.aggregate([ {$currentOp: { allUsers: true ,idleConnections:true} },--取出所有会话 {$project:{IP:{$split:["$client",":"]}}},显示client字段,并按:拆分成数组 {$unwind:"$IP"},--将数组拆分成文档 {$match:{"IP":/^10\./}},--过滤符合条件的文档 {$group:{_id:"$IP",count:{$sum:1}}}—按IP地址分组统计 ]); 以上为例,根据db.currentOp()的输出结果字段信息,结合Mongodb管道的使用,就可灵活的实现各种统计功能和问题定位。 |
--显示当前的活动会话信息
db.aggregate([
{$currentOp: { allUsers: true ,idleConnections:false} },
{$project:{opid:1,client:1,op:1,ns:1,microsecs_running:1}},
{$match:{client:{$exists:true}}},
{$sort:{microsecs_running:-1}}
]);
--查看当前是否有大量会话在等待锁
db.aggregate([
{$currentOp: { allUsers: true ,idleConnections:false} },
{$project:{opid:1,client:1,op:1,ns:1,microsecs_running:1,waitingForLock:1}},
{$match:{"waitingForLock":true}},
{$count:"waitfor locks"}
]);
如果存在大量锁等待,则首先检查是否存在表、库、全局锁:
db.aggregate([
{$currentOp: { allUsers: true ,idleConnections:false} }, {$match:{$or:[{"locks.Global":"W"},{"locks.Database":"W"},{"locks.Collection":"W"}]}}
])
如果发现有会话持有表级、库级或者全局锁,则可根据其opid,执行db.killOp(opid)释放锁资源。如果未发现表级以上的锁,则检查不处于等待状态的会话在做些什么操作,再进行具体处理:
db.aggregate([
{$currentOp: { allUsers: true ,idleConnections:false} },
{$project:{opid:1,client:1,op:1,ns:1,microsecs_running:1,waitingForLock:1}},
{$match:{$and:[{"waitingForLock":false},{client:{$exists:true}}]}},
{$sort:{microsecs_running:-1}}
]);
示例:前台索引创建导致库级锁
模拟在前台创建索引,同时其他会话在相同数据库做读写操作,通过下图可看到有两个会话在等待:


以上查询,均只能查询实时会话情况,如果要查询历史问题,在开启了慢日志的情况下,可以通过后台日志进行跟踪,但是如果在业务量较大的环境下,如果出现锁阻塞,可能会导致大量日志产生,建议使用mtools工具包进行日志分析。




