1、查询当前库慢查询的SQL:
db.system.profile.find({millis:{$gt:5000}}).sort({ts:-1}) ---查询时间超过5s的最近SQL
只显示某些重要指标:
db.system.profile.find({millis:{$gt:1000}},{allUsers:1,client:1,millis:1,nns:1,op:1,query:1,ts:1}).sort({ts:-1})
切割日志文件
db.runCommand({logRotate:1})
但是当实例量非常大的时候,可以直接用如下OS层面的操作来切割日志文件
killall -SIGUSR1 mongod
2、查看当前活跃的连接,运行时间超过3秒,在db1库上进行的操作
db.currentOp({"active":true,"ns":/^exclusive_ipdb./})
2.1、 查询某个IP发起的所有活跃进程
db.currentOp(
{
"active":true,
//"secs_running":{"$gt":3},
"ns":/^exclusive_ipdb\./,
"op" : "update",
//"client":/^10.64.92.74/
}
)
打印某个库下所有活跃连接的IP地址
db.currentOp(
{
"active":true,
"ns":/^exclusive_ipdb\./,
// "secs_running":{"$gt":3}
}
).inprog.forEach(function(x){
print("ip:"+x["client"]+x["ns"])
})
mongos下的活跃连接查看
db.currentOp({"active":true}).inprog.forEach(function(x){
print("ip:"+x["client_s"]+x["ns"])
})
查看某一个client ip下的连接
db.currentOp(true).inprog.forEach(function(x){
var client_str = new String(x["client_s"])
var client_arr = client_str.split(':')
var client_ip = client_arr[0]
if (client_ip == "**10.160.158.93**")
{
print("ip:"+client_str+x["ns"]);
print(tojson(x));
}
})
kill掉相关进程
db.killOp(164686820) ---括号里直接写opid
db.killOp("r37504-2699:17601") ---kill 分片的session需要拷贝整个opid
mongod批量删除进程
db.currentOp(
{
"active":true,
"ns":/^zhike_im/
}
).inprog.forEach(function(x){
print("killed:"+x["client"]+" : "+x["ns"]);
db.killOp(x["opid"]);
})
批量kill掉某一种操作
"op" : "remove" //删除操作
"op" : "query" //查询操作
"op" : "update" //更新操作
循环kill某些SQL
var count=0;
while (count < 100) {
db.currentOp({
"active": true,
"op": "query",
"ns": /^argus_antifraud\./,
"secs_running": {"$gt": 1}
}).inprog.forEach(function(x) {
print("opid:"+x["opid"]+" : "+x["ns"]+"--secs_running:"+x["secs_running"]+ "--ip:"+x["client"]);
db.killOp(x["opid"]);
});
print(count);
sleep(1000);
count++;
}
在mongos上批量kill进程
db.currentOp(
{
"active":true,
"ns":/^netlab_pdns.flint/,
"op" : "remove"
}
).inprog.forEach(function(x){
print("killed:"+x["client_s"]+" : "+x["ns"]);
db.killOp(x["opid"]);
})
kill掉全表扫描的操作
db.currentOp(
{
"active":true,
"ns":/^res\./,
"planSummary" : "COLLSCAN"
}
).inprog.forEach(function(x){
print("killed:"+x["client_s"]+" : "+x["ns"]);
db.killOp(x["opid"]);
})
3.锁相关
3.1、查看当前等待锁状态的进程id
db.currentOp().inprog.forEach(
function(item)
{if (item.waitingForLock == true)
{print(item.opid);}
});
3.2、查看当前持有X锁状态的session
db.currentOp(
{
"active":true,
//"waitingForLock" : true, //等待获取锁
$or:[{"locks.Global":"W"},{"locks.Database":"W"}], //当前持有X锁的session
//"locks.Database" : "W"
}
)
3.3 打印锁信息
db.currentOp().inprog.forEach(function(item){print(tojson(item.locks));})
4、列出所有的连接信息
注:不加true的话表示正在运行的
db.currentOp(true)
在系统层面查看当前端口27047的连接情况(IP地址产生的连接数)
[mongo@mongosms01 ~]5}'|awk -F ':' '{print $1}' | sort | uniq -c | sort -nr
633 10.26.231.103
472 10.26.231.106
378 10.26.231.101
345 10.26.231.102
5、查看当前实例的参数
db.runCommand({getParameter:"*"})
获取当前mongod 或 mongos启动时的配置文件参数
db.serverCmdLineOpts()
6、查看集合和文件的对应关系
db.getMongo().getDBNames().forEach(function(x) {
db.getSiblingDB(x).getCollectionNames().forEach(function(y) {
var z = db.getSiblingDB(x).getCollection(y).stats({
indexDetails: true,
scale: 1024 * 1024 * 1024
});
print(x + "." + y + ", " + z["storageSize"] + " = " + tojson(z["wiredTiger"]["uri"]).replace(/^.icket*:/, "").replace(/.$/, ".wt"));
for ( var key in z["indexSizes"]) {
print(x + "." + y + "." + key + ", " + z["indexSizes"][key] + " = " + tojson(z["indexDetails"][key]["uri"]).replace(/^.*:/, "").replace(/.$/, ".wt"));
}
})
})
查看库下集合的大小
//---数据文件大小
db.getCollectionNames().forEach(function(y) {
var z = db.getCollection(y).stats({
indexDetails: true,
scale: 1024 * 1024
})
print(y + "--------storageSize:-----" + z["storageSize"] +"MB");
})
//---集合总大小(包含索引)
db.getCollectionNames().forEach(function(y) {
var z = db.getCollection(y).stats({scale: 1024 * 1024 * 1024});
var total_size=0;
var storageSize_GB=z["storageSize"];
var indexSize_GB=z["totalIndexSize"];
total_size+=storageSize_GB
total_size+=indexSize_GB
print(y + "---total_size:" + total_size +"GB");
})
查看集合的索引大小
//---集合索引总大小
db.getCollectionNames().forEach(function(y) {
var z = db.getCollection(y).stats({scale: 1024 * 1024 });
var total_size=0;
var indexSize_GB=z["totalIndexSize"];
print(y + "---total_index:" + indexSize_GB +"MB");
})
7、查看当前库下所有表的索引名
db.getCollectionNames().forEach(function(x){
var y = db.getCollection(x).getIndexes();
print(y[0].ns)
for (var i=0,len=y.length;i<len;i++){
print(y[i].name)
}
})
7.1 提取库下某一个表的索引创建语句
var x = 'isc_strategy_user'
var y = db.getCollection(x).getIndexes();
for (var i=0,len=y.length;i<len;i++){
var idx_info=y[i];
if (idx_info.name != "_id_")
{
var fields=idx_info.key;
delete idx_info['v'];
delete idx_info['key'];
delete idx_info['ns'];
print("db."+x+".createIndex\("+tojson(fields)+","+tojson(idx_info)+"\)");
}
}
7.2 提取库下所有表的索引创建语句(MongoDB 5.0之前)
db.getCollectionNames().forEach(function(collname){
if (collname.substring(0,6) == "system"){
return;
}
var y = db.getCollection(collname).getIndexes();
for (var i=0,len=y.length;i<len;i++){
var idx_info=y[i];
if (idx_info.name != "_id_")
{
var fields=idx_info.key;
delete idx_info['v'];
delete idx_info['key'];
delete idx_info['ns'];
if ('background' in idx_info){
print("db."+collname+".createIndex\("+tojson(fields)+","+tojson(idx_info)+"\)");
}
else {
print("db."+collname+".createIndex\("+tojson(fields)+","+tojson(idx_info)+",{background:true}\)");
}
}
}
})
提取库下所有表的索引创建语句(MongoDB 5.0及以后)
db.getCollectionNames().forEach(function(collname){
if (collname.substring(0,6) == "system"){
return;
}
var y = db.getCollection(collname).getIndexes();
for (var i=0,len=y.length;i<len;i++){
var idx_info=y[i];
if (idx_info.name != "_id_")
{
var fields=idx_info.key;
delete idx_info['v'];
delete idx_info['key'];
delete idx_info['ns'];
if ('background' in idx_info){
print("db."+collname+".createIndex\("+**JSON.stringify**(fields)+","+**JSON.stringify**(idx_info)+"\)");
}
else {
print("db."+collname+".createIndex\("+**JSON.stringify**(fields)+","+**JSON.stringify**(idx_info)+",{background:true}\)");
}
}
}
})
注:新版本后,原旧MongoDB shell的一些内置函数不再支持,例如tojson(), 而在新版本mongosh中可以直接用JavaScript的内置方法来替代;
7.3 提取所有库下所有表的索引创建语句
db.getMongo().getDBNames().forEach(function(dbname) {
if (dbname == "admin" ||dbname == "local" || dbname == "config"){
return;
}
print("use "+dbname);
var dbname="utas";
db.getSiblingDB(dbname).getCollectionNames().forEach(function(collname){
if (collname.substring(0,6) == "system"){
return;
}
var y = db.getSiblingDB(dbname).getCollection(collname).getIndexes();
for (var i=0,len=y.length;i<len;i++){
var idx_info=y[i];
if (idx_info.name != "_id_")
{
var fields=idx_info.key;
delete idx_info['v'];
delete idx_info['key'];
delete idx_info['ns'];
if ('background' in idx_info){
print("db."+collname+".createIndex\("+tojson(fields)+","+tojson(idx_info)+"\)");
}
else {
print("db."+collname+".createIndex\("+tojson(fields)+","+tojson(idx_info)+",{background:true}\)");
}
}
}
})
})
8、查看当前在建索引进度
db.currentOp({"active":true, "msg":/^Index/}).inprog.forEach(function(item){ print(item.command.createIndexes+":"+item.msg+" run_time:"+item.secs_running+"s");})
db.currentOp({"active":true, "msg":/^Index/}).inprog.forEach(function(item){ print(item.command.createIndexes+":"+item.command.indexes[0].name+":"+item.msg+" run_time:"+item.secs_running+"s");})
db.currentOp({"active":true, "msg":/^Index/}).inprog.forEach(function(item){ print(tojson(item))})
3.4版本
db.currentOp({"active":true, "msg":/^Index/}).inprog.forEach(function(item){ print(tojson(item.msg))})
mongos分片集群查看索引进度
db.currentOp({"active":true, "msg":/^Index/}).inprog.forEach(function(item){ print(tojson(item.opid));print(tojson(item.msg))})
9、查看初始化节点的同步进度
当你rs.add()新加入一个空节点时,会进行数据的初始化同步,此时如果你想查看同步到什么位置了,可以通过log日志查看
PROD [mongo@db02-drccn1mong sms]#tail -f /data/logs/rs1_logs/rs1.log | grep "clone progress"
2019-04-23T16:31:08.006+0800 I - [repl writer worker 10] APP_MSG_GW.Message collection clone progress: 226280033/462630280 48% (documents copied)
2019-04-23T16:32:18.671+0800 I - [repl writer worker 10] APP_MSG_GW.Message collection clone progress: 229333629/462630280 49% (documents copied)
2019-04-23T16:33:27.810+0800 I - [repl writer worker 10] APP_MSG_GW.Message collection clone progress: 232224979/462630280 50% (documents copied)
2019-04-23T16:34:53.254+0800 I - [repl writer worker 10] APP_MSG_GW.Message collection clone progress: 235135641/462630280 50% (documents copied)
2019-04-23T16:36:15.938+0800 I - [repl writer worker 10] APP_MSG_GW.Message collection clone progress: 238116155/462630280 51% (documents copied)
10、临时备份少量数据:
类似于insert into table_bk select xxxx from t1 where field=xxx;
db.t1.find({username:'xxx'}).forEach(function(x){
db.t1_bk.insert(x);
});
11、获取当前库下所有表的可收缩空间:
db.getCollectionNames().forEach(function(x){
var y = db.getCollection(x).stats().wiredTiger['block-manager']['file bytes available for reuse'];
print(x +":"+ y/1024/1024);
})
12、查看server上某个端口实例的连接数情况
netstat -nal |grep ":27097"|awk '{print 1}' | sort | uniq -c | sort -nr
188 10.67.4.6
164 10.67.231.92
156 10.67.4.8
150 10.67.4.7
13.Sharding基本操作
查看分片状态:sh.status() 或 db.printShardingStatus()
查看分片库有哪些:
use config
db.databases.find( { "partitioned": true } )
查看当前有哪些分片:db.adminCommand( { listShards : 1 } )
14.权限
查看角色权限:
db.runCommand({rolesInfo:'read',showPrivileges:1})
分配权限给角色
db.grantPrivilegesToRole("dbarole",[{resource:{db:"config","collection":"collections"},actions:["find"]}])
回收权限从角色
db.revokePrivilegesFromRole("dbarole",[{resource:{db:"config","collection":"collections"},actions:["find"]}])
批量回收角色上的权限
db.runCommand({rolesInfo:'dbarole',showPrivileges:1}).roles[0].inheritedPrivileges.forEach(function(x)
{print('db.revokePrivilegesFromRole("dbarole",[{resource:'+ tojson(x['resource']) + ',actions:["dropIndex"]}])');}
)
注:当然你也可以使用以上脚本来生成批量赋予权限的命令;
15.获取sharding下的节点信息
mongos> db.adminCommand({listShards:1}).shards.forEach(function(x){print(x["host"]);})
7565/10.208.134.95:7565,10.208.61.223:7565
7567/10.208.136.238:7567,10.208.37.36:7567
7250/10.208.58.54:7250,10.208.64.117:7250
7997/10.145.70.113:7997,10.208.61.145:7997
16.获取分片集合的总行数
有时候直接coll.count()得出的结果是统计信息的结果,有可能不准确,此时我们可以使用如下命令:
db.collName.aggregate([
{sum":1}}}
])
17.获取sharding架构下,数据总大小
var data=db.stats()['raw']
total_data_size=0
total_index_size=0
total_storageSize=0
for(i in data){
var shard_data=data[i];
var dataSize=shard_data['dataSize'];
var indexSize=shard_data['indexSize'];
var storageSize=shard_data['storageSize'];
total_data_size+=dataSize
total_index_size+=indexSize
total_storageSize+=storageSize
}
print("total_data_size_TB:"+Math.round(total_data_size/1024/1024/1024/1024))
print("total_index_size_TB:"+Math.round(total_index_size/1024/1024/1024/1024))
print("total_storageSize:"+Math.round(total_index_size/1024/1024/1024/1024))
18.获取sharding架构下,每个主分片的storageSize大小
var data=db.stats()['raw']
total_data_size=0
total_index_size=0
total_storageSize=0
for(i in data){
var shard_data=data[i];
var shard_name=i.split(':').slice(-1)[0];
var dataSize=shard_data['dataSize'];
var indexSize=shard_data['indexSize'];
var storageSize=shard_data['storageSize'];
print(shard_name+":"+Math.round(storageSize/1024/1024/1024));
}
19.查看数据库数量
当数据库数量非常多时,我们可能无法直观的得到库的数量,可以通过如下命令查看到
db.runCommand({listDatabases:1}).databases.length
20.提取分片集合的分片结构
即生成集合的分片创建语句,在config库下执行,方便在新库上建立集合分片
db.getSiblingDB('config').collections.find().forEach(function(x){
if (x["dropped"] == true){
return;
}
var ns = x["_id"]
var shard_key = x["key"]
print("sh.shardCollection\(\"" + ns + "\"," + tojson(shard_key) + "\)");})
21.查看collection下索引的调用情况:
db.MyColl.aggregate([{ $indexStats:{} }]).pretty()
22.降低某一个副本集角色的被选举权
rs.freeze(seconds)
23.批量查询库
当库数量非常大,需要根据库名前缀来查询,可以使用如下脚本:
db.getMongo().getDBNames().forEach(function(dbname) {
if (dbname == "admin" ||dbname == "local" || dbname == "config"){
return;
}
var regex=/^u/
if (regex.test(dbname)){
print(dbname);
}
})
注:可以根据需求来变更regex的正则规则,正则规则参考:https://juejin.cn/post/6844903487155732494
批量删除库:
db.getMongo().getDBNames().forEach(function(dbname) {
if (dbname == "admin" ||dbname == "local" || dbname == "config"){
return;
}
var regex=/^haha/
if (regex.test(dbname)){
print(dbname);
use
}
})
24.查看当前所有库下的集合数量
有时候DB数量太多,我们想要只要每一个库下的集合数量
db.getMongo().getDBNames().forEach(function(dbname) {
if (dbname == "admin" ||dbname == "local" || dbname == "config"){
return;
}
var coll_infos=db.getSiblingDB(dbname).getCollectionNames().length;
print(dbname," coll count: ",coll_infos);
})
25.获取集合中每行的字段数量
因为有的时候业务会随意写数据,每个document的field字段个数也不一样,所以如果想要统计每行的字段数量,可以参考如下脚本:
db.tb2.find().forEach(function(x){
var count=Object.keys(x).length;
print(x["_id"] + ":"+count);
db.tmp1.insert({"_id":x["_id"],"count":count});
})
注:这种是我想到的初级版本,如果集合数据量很大的话,会消耗较多资源
26.强制将剩余可用节点reconfig副本集
有时候副本由于小于大多数,导致副本集不可写,随可以使用如下脚本强制将副本集变为可写
// 获取可用的节点
var availableHost=[];
rs.status().members.forEach(function(obj){
if (obj.stateStr == "SECONDARY" || obj.stateStr == "PRIMARY"){
availableHost.push(obj.name);
print(obj.name);
}
});
// 获取重新配置的可用节点
var new_conf=rs.config();
rs.config().members.forEach(function(obj,index){
if (!availableHost.includes(obj.host)){
new_conf.members.splice(index,1);
}
});
// 重新配置
rs.reconfig(new_conf,{force:true});
27、获取当前库下所有表的可收缩空间(数据节点):
db.getCollectionNames().forEach(function(x){
var y = db.getCollection(x).stats().wiredTiger['block-manager']['file bytes available for reuse'];
print(x +" : "+ Math.round(y/1024/1024) + " MB");
})