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

文摘   2024-10-09 06:00   天津  

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,可以解决你的问题。加群请联系 liuaustin3 ,(共2400人左右 1 + 2 + 3 + 4 +5 + 6 + 7)(1 2 3 4 5 群均已爆满,请不要在问有没有位置谢谢, 6群超过400人停止自由申请,7群开启)

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(1, 100);  

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

   
    var slowQueries = db.system.profile.find({
        millis: { $gt: 100 }  
    }).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 * 1000; 


while (elapsed < waitTime) {
    var currentTime = new Date().getTime();
    elapsed = currentTime - startTime;
}


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


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

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


置顶文章


开发问MySQL 大事务证据,一个脚本堵上他的嘴

撕逼!PostgreSQL 和 MongoDB 开撕,MySQL却躺枪

MongoDB  系统IOPS 告警系统处于崩溃,优化语句从1秒优化到1毫秒解决问题

MongoDB 入门教学贴 从术语到操作 (约束怎么建立  内部培训贴)

MongoDB 谨献给说MongoDB 这不好那不好的“古董”  -- 发展与演进,从3 到 7 的卓越变化

MongoDB 的一张“大字报”  服务客户,欢迎DISS

专访唐建法-从MongoDB中国第一人到TapData掌门人的故事

DBA 失职导致 PostgreSQL 日志疯涨



往期热门文章:


微软 “爱” 上PostgreSQL, PG  “嫁给” 微软!

PostgreSQL 软肋 “最大连接数” 到底是不是问题?

PostgreSQL 具有createdb的用户无法创建数据库的原因(之一)
PostgreSQL 同样的语句 一会快 一会慢到底怎么回事,
云原生数据库是青出于蓝胜于蓝,还是数据库产品的倒退?
MySQL 8.0x 到 9.0均可能崩溃--云厂商开发指责 MYSQL不测试就推新版本?

阿里云数据库--市场营销聊胜于无--3年的使用感受与反馈系列

阿里云数据库产品 对内对外一样的卷 --3年阿里云数据库的使用感受与反馈系列

阿里云数据库使用感受--客户服务问题深入剖析与什么是廉价客户 --3年的使用感受与反馈系列

阿里云数据库使用感受--操作界面有点眼花缭乱 --3年的使用感受与反馈系列

临时工说:DBA 7*24H 给2万的工作,到底去不去?

PolarDB 最近遇到加字段加不上的问题 与 使用PolarDB 三年感受与恳谈

PostgreSQL 稳定性平台 PG中文社区大会--杭州来去匆匆

MySQL 让你还用5.7 出事了吧,用着用着5.7崩了

临时工访谈:问金融软件开发总监  哪些业务不用传统数据库
PolarDB  Serverless POC测试中有没有坑与发现的疑问
临时工访谈:PolarDB Serverless  发现“大”问题了  之 灭妖记 续集
临时工访谈:庙小妖风大-PolarDB 组团镇妖 之 他们是第一
PolarDB for PostgreSQL  有意思吗?有意思呀
PolarDB  Serverless POC测试中有没有坑与发现的疑问

MySQL 的SQL引擎很差吗?由一个同学提出问题引出的实验

临时工访谈:从国产数据库 到 普罗大众的产品 !与在美国创业软件公司老板对话

PostgreSQL 如何通过工具来分析PG 内存泄露

MySQL 的SQL引擎很差吗?由一个同学提出问题引出的实验
临时工访谈:我很普通,但我也有生存的权利,大龄程序员 求职贴
临时工说: 快速识别 “海洋贝壳类” 数据库方法速递
临时工说:国产 数据库 销售人员  图鉴
临时工说:DBA 是不是阻碍国产数据库发展的毒瘤 ,是不是?从国产DB老专家的一条留言开始 (其实更好看的是文章下方的留言)

感谢 老虎刘 刘老师 对 5月20日 SQL 问题纠正贴 ---PostgreSQL 同一种SQL为什么这样写会提升45%性能

PostgreSQL 同一种SQL为什么这样写会提升45%性能 --程序员和DBA思维方式不同决定

MongoDB 不是软柿子,想替换就替换

PostgreSQL  熊灿灿一句话够学半个月 之 KILL -9

MongoDB  挑战传统数据库聚合查询,干不死他们的

临时工说:国内数据库企业存活   “三板斧”

临时工访谈:庙小妖风大-PolarDB 组团镇妖 之 他们是第一  (阿里云组团PK笔者实录

临时工访谈:金牌 “女” 销售从ORACLE 转到另类国产数据库 到底  为什么?

临时工访谈:无名氏意外到访-- 也祝你好运(管理者PUA DBA现场直播)

临时工说:搞数据库 光凭的是技术,那DBA的死多少次?

PostgreSQL  分组查询可以不进行全表扫描吗?速度提高上千倍?
临时工说:分析当前经济形势下 DBA 被裁员的根因
PostgreSQL PG_DUMP 工作失败了怎么回事及如何处理
MySQL 八怪(高老师)现场解决问题实录
PostgreSQL 为什么也不建议 RR隔离级别,MySQL别笑
临时工访谈:OceanBase上海开大会,我们四个开小会 OB 国产数据库破局者
临时工说:OceanBase 到访,果然数据库的世界很卷,没边
临时工访谈:恶意裁员后,一个国产数据库企业程序员的心声
临时工说:上云后给 我一个 不裁 DBA的理由
PolarDB for PostgreSQL  有意思吗?有意思呀
PostgreSQL   玩PG我们是认真的,vacuum 稳定性平台我们有了
临时工说:裁员裁到 DBA 咋办  临时工教你 套路1 2 3
PolarDB  搞那么多复杂磁盘计费的东西,抽筋了吗?
临时工说:OceanBase 到访,果然数据库的世界很卷,没边
MONGODB  ---- Austindatabases  历年文章合集
MYSQL  --Austindatabases 历年文章合集
POSTGRESQL --Austindatabaes 历年文章整理
POLARDB  -- Ausitndatabases 历年的文章集合
PostgreSQL  查询语句开发写不好是必然,不是PG的锅
SQL SERVER 如何实现UNDO REDO  和PostgreSQL 有近亲关系吗
MongoDB 2023纽约 MongoDB 大会 -- 我们怎么做的新一代引擎 SBE Mongodb 7.0双擎力量(译)
MongoDB 2023年度纽约 MongoDB 年度大会话题 -- MongoDB 数据模式与建模
MongoDB  双机热备那篇文章是  “毒”
MongoDB   会丢数据吗?在次补刀MongoDB  双机热备
临时工说:从人性的角度来分析为什么公司内MySQL 成为少数派,PolarDB 占领高处
POLARDB  到底打倒了谁  PPT 分享 (文字版)
PostgreSQL  字符集乌龙导致数据查询排序的问题,与 MySQL 稳定 "PG不稳定"
PostgreSQL  Patroni 3.0 新功能规划 2023年 纽约PG 大会 (音译)

Austindatabases 公众号,主要围绕数据库技术(PostgreSQL, MySQL, Mongodb, Redis, SqlServer,PolarDB, Oceanbase 等)和职业发展,国外数据库大会音译,国外大型IT信息类网站文章翻译,等,希望能和您共同发展。
截止今天共发布 1226篇文章

AustinDatabases
关于数据库相关的知识分享
 最新文章