MongoDB性能監(jiān)控與其他數據庫對比
Mongodb是一種單進程且靈活的非關系型數據庫。但由于其軟件小巧,單進程多線程的特點注定不會存在完善的系統動態(tài)性能視圖,這點與mysql類似,但個人認為即便與mysql對比,不足還是顯而易見。此外,對于運維人員來說,多數人習慣使用字符終端處理問題,由于mongodb是基于json,所以輸出都是json格式,這點跟關系型數據庫輸出的行列格式相比,個人感覺可讀性相對較差。所以,基于運維需要的MongDB監(jiān)控能力補齊,是運維工作不可或缺工作之一,至于是腳本形式還是工具平臺形式,都可以基于各自已有IT能力水平有計劃分步驟的進行實施。畢竟不管白貓黑貓,能抓老鼠的就是好貓。
數據庫性能數據獲取診斷方式對比:
mongodb性能監(jiān)控詳細介紹
在數據庫日常運維過程中,數據庫性能監(jiān)控是重點工作之一。對于mongodb來說,由于在數據庫中不會保存歷史性能信息,所以我們只能通過使用集中監(jiān)控軟件或者自己編寫腳本的方式采集性能數據保存在本地,本文只介紹利用Mongodb自帶工具或者命令采集性能數據。
1、操作系統資源使用率監(jiān)控
操作系統CPU、內存、IO等資源使用率監(jiān)控,在任一數據庫產品都需要部署,本文不再闡述。
2、mongotop&&mongostat
mongotop和mongostat是mongodb官方提供的兩個在不同級別對數據庫性能進行監(jiān)控的工具,可以獲取到實例全局和表級的性能數據。通過在操作系統上部署定時任務的方式執(zhí)行這兩個命令并將結果輸出保存,可用于歷史性能分析。
1)、mongotop
返回數據庫集合級別的讀寫耗時情況,輸出結果按照讀寫耗時降序排列,排序越靠前表示該集合訪問并發(fā)越大或者說該集合上執(zhí)行的MQL語句執(zhí)行計劃不是最優(yōu)。輸出結果示例如下:
2)、mongostat
mongostat類似操作系統的vmstat命令,返回實例全局每秒鐘整體性能情況,包括讀寫次數、內存占用,鎖隊列、網絡、連接數等信息。如果是集群,建議使用—discover參數獲取集群全局信息。
oracle有一個監(jiān)控利器叫Oswatcher,使用mongostat&&mongotop合理編寫腳本,在用crontab定時調用,可實現類似oswatcher的功能,作為歷史性能數據分析。
3、慢查詢分析
mongodb的慢查詢,可以通過設置profile后,在system.profile集合或者在數據庫日志中獲取。設置命令為db.setProfilingLevel(level,options),如db.setProfilingLevel(1,{ slowms: 200 }),表示級別為1,超過200ms的操作將被捕獲,設置級別為0表示不捕獲,級別為2表示捕獲所有操作。可通過db.getProfilingStatus()命令查詢當前的profile設置級別。
1)、system.profile
system.profile是通過使用db.setProfilingLevel(level,options)命令設置后在每一個庫中生成的固定大小為1MB的集合,該集合根據設置的profile級別保存所有或者超過指定時間的操作命令信息,當保存數據過多超過1MB時,會自動清理歷史數據。
保存信息示例:
{
"op": "query", ? --操作類型為查詢
"ns": "opn###od.optN###em", --操作的庫名.集合名
"command": {
"find": "optNu###tem", ?--集合名稱
"filter": { ?--過濾條件
"_id": {
"res##id": "1000000000000003733049",
"res##etype": "3002"
}
},
"limit": 1, ?--limit條數
"singleBatch": true,
"$db": "opnu###od" ?--庫名
},
"keysExamined": 0,
"docsExamined": 0,
"cursorExhausted": true,
"numYield": 0,
"locks": { ? ---本次操作的鎖信息
"Global": {
"acquireCount": {
"r": NumberLong(2)
}
},
"Database": {
"acquireCount": {
"r": NumberLong(1)
}
},
"Collection": {
"acquireCount": {
"r": NumberLong(1)
}
}
},
"nreturned": 0,
"responseLength": 237,
"protocol": "op_query",
"millis": 77432, ? --操作耗時,單位為毫秒
"planSummary": "IDHACK", ---執(zhí)行計劃類型
"execStats": {
"stage": "IDHACK",
"nReturned": 0,
"executionTimeMillisEstimate": 0,
"works": 1,
"advanced": 0,
"needTime": 0,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"keysExamined": 0,
"docsExamined": 0
},
"ts": ISODate("2019-11-14T06:47:45.285Z"),--操作時間
"client": "10***227", ?---客戶端IP
"allUsers": [
{
"user": "user_admin",
"db": "admin"
}
],
"user": "user_admin@admin"
}
向上滑動查看更多內容
2)、從日志中獲取慢查詢
在mongodb的后臺日志中會同時記錄一份慢查詢信息,相對于system.profile集合的優(yōu)點是會永久保存,缺點是需要從海量的日志中過濾慢日志信息,不過若數據庫的性能較差且并發(fā)較大,此時可看到日志上有大量的慢查尋日志刷屏,一般也可快速定位問題。
日志中輸出的內容跟system.profile保存的基本一致,只是可讀性稍微較差些,示例見上圖。
4、當前會話操作獲取
在mongodb中,如需獲取當前的會話信息,可使用db.currentOp()命令,該命令獲取到的信息,類似于在oracle中通過聯合查詢v$session和v$process獲取到的信息,包含客戶端類型、IP、正在執(zhí)行的命令、正在操作的對象、執(zhí)行計劃、鎖等等詳細信息,其中包括活動會話和非活動會話信息。對于自己需要的信息,可通過相關的過濾條件進行過濾,如下示例:
--獲取活動會話信息
db.currentOp(
{
"active": true
}
)
--查詢所有在等待鎖,且操作命令為增刪改的會話信息。
db.currentOp(
{
"waitingForLock": true,
$or:[
{"op" : { "$in" : [ "insert", "update","remove" ] } },
{"query.findandmodify": { $exists: true } }
]
}
)
從3.6版本開始,提供了$currentOp這個聚合管道階段,可以更加靈活的獲取到當前的會話操作信息,并且返回的是游標,規(guī)避了db.currentOp的最大16MB的BSON大小限制。
--獲取活動會話,
useadmin
db.aggregate([
{$currentOp: { allUsers: true ,idleConnections:false} },
{$project:{opid:1,client:1,op:1,ns:1,microsecs_running:1}},
{$match:{client:{$exists:true}}}
]);
針對獲取到的異常會話或者執(zhí)行時間長的會話,可以通過db.killOp()命令kill客戶端會話。
常見性能問題處理
1、通過創(chuàng)建索引優(yōu)化慢查詢
跟其他關系型數據庫一樣,當出現對大量的慢查詢時,可以檢查其執(zhí)行計劃,若執(zhí)行計劃是全表掃描(COLLSCAN)語句時,可以通過在選擇性較高的過濾條件上創(chuàng)建索引來優(yōu)化查詢。db.collection.createIndex({field:1},{background,true});
注:生產系統創(chuàng)建索引一定必須在后臺創(chuàng)建索引,即指定{background,true},否則會產生庫級鎖
2、數據庫阻塞處理
mongodb作為一款輕量級nosql數據庫,在并發(fā)鎖控制上相對弱些。部分操作會加庫級鎖,如前臺創(chuàng)建索引、碎片整理、repair等,庫級鎖會阻塞當前數據庫的所有操作,最明顯的表現就是會導致數據庫會話數逐漸上升,阻塞時間長還會導致連接數爆滿。此類操作一般會記錄在后臺日志中,通過db.currentop()也可獲取會話信息,然后通過db.killOp()命令kill會話。注:killop只能kill客戶端會話,并且不是所有的操作都可以kill。
3、內存優(yōu)化處理
在3.2版本以后,默認使用wiredtiger存儲引擎,可以通過參數cacheSizeGB設置存儲引擎的內存使用上限,默認是系統內存的60%??梢酝ㄟ^mongostat觀察內存cache的使用情況,一般情況下used會小于80%,如果長時間的used達90%或者dirty10%,可考慮增加內存或者檢查IO 。
4、數據庫寫入性能較差
寫入性能差,需確定是整體性能差還是某個集合寫入性能差,如果是整體都差的話,需檢查IO,考慮更換性能更好的存儲或者進行分片打散IO。如果是某個集合寫入性能差,則需要檢查這個集合是否索引過多,或者高并發(fā)或者異常語句導致異常加鎖。
--查詢在某個庫中從未使用過的索引,如果索引長期未使用,建議刪除
db.getCollectionNames().forEach(function(collection){
if(db[collection].getIndexes().length != 1){
print("Indexesfor "+ collection + ":");
db[collection].aggregate([{
$indexStats:{}
},{
$project:{
host:0
}
}]).forEach(
function(opDoc){
if(opDoc.accesses.ops== 0&& opDoc.name!= "_id_"){
printjson(opDoc);
}
});
}
});
向上滑動查看更多內容
5、便捷的數據生命周期管理
TTL索引是MongoDB中一種特殊的索引,可以支持文檔在一定時間之后自動過期刪除??梢栽俪齙id外的所有字段上建立,但是只有在當字段值是時間或者數組中包含時間時,TTL索引才會執(zhí)行刪除操作,數組中包含多個時間時,按照數組中最小的時間計算。
例:db.collection.createIndex({ "InsertTime": 1 }, { expireAfterSeconds: 2592000?} );
6、內存數據庫引擎
Mongodb企業(yè)版擁有自己的內存數據庫引擎,但是需要收費。在社區(qū)版中,可將數據文件(dbpath)放入/de/shm中,變相使用內存引擎。
注:由于內存一般不會太大,建議合理選擇業(yè)務,并使用固定大小集合。
版權聲明:
本站所有文章和圖片均來自用戶分享和網絡收集,文章和圖片版權歸原作者及原出處所有,僅供學習與參考,請勿用于商業(yè)用途,如果損害了您的權利,請聯系網站客服處理。