瞬间成为MongoDB专家,8个脚本都写好了,一用一个不吱声【转】

MongoDB 最近一直在写文言文,但咱们MongoDB也是武行出身,今天就说说那些MongoDB的具有一些技术含量,且你需要的脚本,有这些脚本,能让小白快速解决一些问题,短暂冒充小专家。

这里需要注意,运行下面的脚本,一定要使用mongosh,不会装的看下面的,其实不用装,下载就放到Linux中的 /bin 中就可以了。

https://www.mongodb.com/try/download/shell

图片

下面咱们就来顺序着来,8个JS脚本,咱们也不要版权,就是用的时候,想着点我好图片

脚本1:分析MongoDB 中所有库和每个库里面的collation的大小,存储空间整体索引使用的空间,等等,一个脚本可以让数据库里面所有的表大小你都获知。

图片

这里注意,在链接得时候,你要有足够的权限,权限不够脚本运行不了,尤其是一些管理信息类的命令,你要是怕权限不够,可以直接用mongodb 的root权限账号来运行,这里注意 db = connect('mongodb://root:1234.Com@192.168.198.100:27027/admin') 每个脚本里面都有连接的信息,其中root是账号名,1234.Com 是密码,你可以将对应你的monogDB库的用户名密码替换即可,同时后面是IP和端口号 admin指的是admin库,下面是代码和每个代码运行后的结果图。

db = connect('mongodb://root:1234.Com@192.168.198.100:27027/admin');

var databases = db.adminCommand({ listDatabases: 1 }).databases;

databases.forEach(function(dbInfo{
    print("Database Name: " + dbInfo.name);
});

dbStats = db.runCommand({ dbStats: 1 });

collectionStats = db.getCollectionNames().map(function(collectionName{
    return db.getCollection(collectionName).stats();
});

print("=== Database Statistics ===");
print("Database Name: " + dbStats.db);
print("Number of Collections: " + collectionStats.length);

totalDocuments = 0;
totalAvgObjSize = 0;
totalDataSize = 0;

collectionStats.forEach(function(collection{
    totalDocuments += collection.count;
    totalAvgObjSize += collection.avgObjSize || 0;
    totalDataSize += collection.size;
    print("Collection: " + collection.ns);
    print("  Document Count: " + collection.count);
    print("  Avg Object Size: " + (collection.avgObjSize / 1024).toFixed(2) + " KB");
    print("  Collection Size: " + (collection.size / 1024 / 1024).toFixed(2) + " MB");
});

print("=== Summary ===");
print("Total Documents: " + totalDocuments);
print("Total Avg Object Size: " + (totalAvgObjSize / collectionStats.length / 1024).toFixed(2) + " KB");
print("Total Data Size: " + (totalDataSize / 1024 / 1024).toFixed(2) + " MB");

图片

脚本2 第一个脚本没有汇总信息,第二个脚本有汇总信息,包含每个document的平均大小,和数据总体的尺寸。


db = connect('mongodb://root:1234.Com@192.168.198.100:27027/test');

var operations = db.currentOp();

var activeConnections = 0;
var idleConnections = 0;
var errorConnections = 0;

operations.inprog.forEach(function(op{
 
    if (op.hasOwnProperty('client')) {
        print("Client Address: " + op.client);
        print("App Name: " + (op.appName ? op.appName : "N/A"));
        print("Operation ID (opid): " + op.opid);
        print("Database: " + (op.ns ? op.ns.split('.')[0] : "N/A"));
        print("Secs Running: " + (op.hasOwnProperty('secs_running') ? op.secs_running : "N/A") + " seconds");

        if (op.active) {
            activeConnections++;
            print("  Status: Active");
        } else if (!op.active && op.hasOwnProperty('secs_running') && op.secs_running == 0) {
            idleConnections++;
            print("  Status: Idle");
        } else if (op.hasOwnProperty('msg') && op.msg == "error") {
            errorConnections++;
            print("  Status: Error");
        }
        
        print(""); 
    }
});

print("\n=== Connection Summary ===");
print("Active Connections: " + activeConnections);
print("Idle Connections: " + idleConnections);
print("Error Connections: " + errorConnections);

图片

脚本3 这个脚本是分析当前连接的,且总结当前链接中有多少活跃的链接,多少idle的,并打印出每个链接已经工作的时间


db = connect('mongodb://root:1234.Com@192.168.198.100:27027/test');

var operations = db.currentOp();

var activeConnections = 0;
var idleConnections = 0;
var errorConnections = 0;

operations.inprog.forEach(function(op{
 
    if (op.hasOwnProperty('client')) {
        print("Client Address: " + op.client);
        print("App Name: " + (op.appName ? op.appName : "N/A"));
        print("Operation ID (opid): " + op.opid);
        print("Database: " + (op.ns ? op.ns.split('.')[0] : "N/A"));
        print("Secs Running: " + (op.hasOwnProperty('secs_running') ? op.secs_running : "N/A") + " seconds");

        if (op.active) {
            activeConnections++;
            print("  Status: Active");
        } else if (!op.active && op.hasOwnProperty('secs_running') && op.secs_running == 0) {
            idleConnections++;
            print("  Status: Idle");
        } else if (op.hasOwnProperty('msg') && op.msg == "error") {
            errorConnections++;
            print("  Status: Error");
        }
        
        print(""); 
    }
});

print("\n=== Connection Summary ===");
print("Active Connections: " + activeConnections);
print("Idle Connections: " + idleConnections);
print("Error Connections: " + errorConnections);

图片

脚本4 这个脚本需要具有管理员权限,这个脚本是直接杀死在MongoDB 查询超过30秒的语句,当然时间你可以调

db = connect('mongodb://root:1234.Com@192.168.198.100:27027/test');

var operations = db.currentOp();

operations.inprog.forEach(function(op{
    if (op.secs_running > 30 && op.op === 'query' && !op.killPending) {
       
        print("\n=== Query Details ===");
        print("Operation ID (opid): " + op.opid);
        print("Running for: " + op.secs_running + " seconds");
        print("Client: " + op.client);
        print("Database: " + (op.ns ? op.ns.split('.')[0] : "N/A"));
        print("Collection: " + (op.ns ? op.ns.split('.')[1] : "N/A"));
        print("Query: " + tojson(op.query));
        
      
        var killOp = prompt("Kill this query? (Y/N): ");

        if (killOp.toLowerCase() === 'y') {
      
            print("Killing opid: " + op.opid);
            db.killOp(op.opid);
        } else {
        
            print("Skipping opid: " + op.opid);
        }
    }
});

图片

脚本 5 一般情况下,如果让你找当前的MongoDB中的query 是否有全表扫描,让你立即分析当前MongoDB运行的语句有没有全表扫描,怎么办,来脚本给你准备好了

db = connect('mongodb://root:1234.Com@192.168.198.100:27027/test');


var operations = db.currentOp();


function isTableScan(query{
   
    if (!query || Object.keys(query).length === 0) {
        return true;
    }

    if (!query.hasOwnProperty('_id')) {
        return true;
    }

    return false;
}

var hasTableScan = false;


operations.inprog.forEach(function(op{
    if (op.op === 'query' && !op.killPending) {
        var query = op.query;

      
        if (isTableScan(query)) {
            hasTableScan = true; 

            print("\n=== Potential Table Scan Detected ===");
            print("Operation ID (opid): " + op.opid);
            print("Client: " + op.client);
            print("Database: " + (op.ns ? op.ns.split('.')[0] : "N/A"));
            print("Collection: " + (op.ns ? op.ns.split('.')[1] : "N/A"));
            print("Query: " + tojson(query));
        }
    }
});


if (!hasTableScan) {
    print("没有全表扫描。");
}

图片

脚本 7 基本上MongoDB 大部分都是以replica的形式来出现的,那么怎么分析你的复制有没有延迟,你的这几个节点都是谁,都是什么关系,那就得用下面两个脚本

第一个分析节点之间的关系,且这些库是否正常

db = connect('mongodb://root:1234.Com@192.168.198.100:27027/test');


var serverStatus = db.serverStatus();


print("MongoDB 启动时间 (秒): " + serverStatus.uptime);


var isMaster = db.isMaster();

if (isMaster.ismaster) {
    print("MongoDB 运行模式: 主库 (Primary)");
} else if (isMaster.secondary) {
    print("MongoDB 运行模式: 从库 (Secondary)");
} else {
    print("MongoDB 运行模式: 单机或其他");
}


if (isMaster.setName) {
    print("副本集名称: " + isMaster.setName);

   
    var replStatus = rs.status();

   
    replStatus.members.forEach(function(member) {
        print("\n成员: " + member.name);
        print("  状态: " + member.stateStr);

        if (member.stateStr === "PRIMARY") {
            print("  角色: 主库 (Primary)");
        } else if (member.stateStr === "SECONDARY") {
            print("  角色: 从库 (Secondary)");
        } else if (member.stateStr === "ARBITER") {
            print("  角色: 仲裁节点 (Arbiter)");
        } else if (member.hidden) {
            print("  角色: 隐藏节点 (Hidden)");
        }

        print("  健康状态: " + (member.health === 1 ? "正常" : "异常"));

     
        if (member.syncingTo) {
            print("  正在同步: " + member.syncingTo);
        }

       
        if (member.electionDate) {
            print("  最近的主节点选举时间: " + member.electionDate);
        }
    });
} else {
    print("MongoDB 不是副本集,可能是单机模式。");
}

第二个脚本,是分析复制结合中是否有延迟

db = connect('mongodb://root:1234.Com@192.168.198.100:27027/test');


var replStatus = rs.status();


var primaryOptime = null;
replStatus.members.forEach(function(member{
    if (member.stateStr === "PRIMARY") {
        primaryOptime = member.optimeDate; // 主节点的 optimeDate
        print("主节点: " + member.name);
        print("主节点最后操作时间 (optime): " + primaryOptime);
    }
});


replStatus.members.forEach(function(member{
    if (member.stateStr === "SECONDARY") {
        print("\n从节点: " + member.name);

      
        var secondaryOptime = member.optimeDate;
        print("从节点最后操作时间 (optime): " + secondaryOptime);

    
        var lagSeconds = (primaryOptime - secondaryOptime) / 1000// 将毫秒转换为秒

        if (lagSeconds > 0) {
            print("延迟时间 (秒): " + lagSeconds);
        } else {
            print("无延迟");
        }

       
        if (member.syncingTo) {
            print("正在从节点同步: " + member.syncingTo);
        }
    }
});

图片图片

脚本 8  MongoDB的慢查询和其他的数据库不太一样,因为速度太快,太多的慢查询信息会对数据库的性能产生影响,所以一般MongoDB DBA的习惯是需要的时候打开慢查询,不需要的时候关上,所以这个脚本就是一个这样的脚本,默认打开,然后收集10分钟的慢查询后,将信息打印出来,这里如果要记录可以用LINUX 的 > 重定向将打印的信息重定向到文件中,后面在分析。

db = connect('mongodb://root:1234.Com@192.168.198.100:27027/test');


print("正在设置慢查询阈值为 100 毫秒...");
db.setProfilingLevel(1100);  

function collectSlowQueries() {
    print("\n=== 收集到的慢查询日志 ===");

   
    var slowQueries = db.system.profile.find({
        millis: { $gt100 }  
    }).sort({ ts: -1 }); 

    slowQueries.forEach(function(query) {
        print("查询时间: " + query.ts);
        print("执行时间 (毫秒): " + query.millis);
        
       
        if (query.query) {
            print("查询操作: ");
            printjson(query.query);
        } else {
            print("查询操作: 无查询条件 (如 insert 操作)");
        }

     
        print("数据库: " + query.ns);

      
        if (query.op) {
            print("完整操作: " + query.op);
        } else {
            print("完整操作: 无详细操作类型");
        }

        print("\n");
    });
}


print("开始记录慢查询日志,等待 10 分钟...");

var startTime = new Date().getTime(); 
var elapsed = 0;
var waitTime = 10 * 60 * 1000while (elapsed < waitTime) {
    var currentTime = new Date().getTime();
    elapsed = currentTime - startTime;
}


print("收集 10 分钟内的慢查询...");
collectSlowQueries();


db.setProfilingLevel(0);  
print("已关闭慢查询日志记录。");

以上就是今天给大家分享的8个MongoDB的管理脚本,有的还可以进行改造,但请注意里面有一个问题,部分脚本的默认库是test,那么你的数据库里面就没有test 那么就一定会报错,所以,如果你连这个都不懂,还是先弄懂MongoDB的连接串和简单的与原理在用,我怕你部分脚本乱搞,惹祸。

 

转自

瞬间成为MongoDB专家,8个脚本都写好了,一用一个不吱声
https://mp.weixin.qq.com/s?__biz=Mzg4NDA0NTEwNA==&mid=2247503478&idx=1&sn=3d6fa14f65c6b514ace9560149e38f74&chksm=cfbcaa29f8cb233f5818243294743b1e5f449e84cedc1028c7bab9ab5786db8fa304b4f69afe&scene=21#wechat_redirect

posted @   paul_hch  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2020-01-21 su: 无法设置用户ID: 资源暂时不可用【转】
2019-01-21 MySQL平滑删除数据的小技巧【转】
2019-01-21 Linux下间隔多少秒 (即以秒为单位) 去执行某条命令或某个shell脚本的操作方法【转】
点击右上角即可分享
微信分享提示