【原文】https://scalegrid.io/blog/how-to-stop-a-runaway-index-build-in-mongodb/
【譯文】
在MongoDB上建索引可能會(huì)對(duì)MongoDB集群對(duì)可用性產(chǎn)生負(fù)面影響。在生產(chǎn)服務(wù)上,如果針對(duì)一個(gè)大集合觸發(fā)建立索引,且在前臺(tái)運(yùn)行,你可能會(huì)發(fā)現(xiàn),在索引建完之前,整個(gè)集群都無(wú)影響。在一個(gè)大集合上,這個(gè)過(guò)程可能會(huì)持續(xù)幾個(gè)小時(shí),甚至幾天。
推薦的最佳做法是,觸發(fā)建索引,但讓其在后臺(tái)運(yùn)行。然而,當(dāng)是大集合的索引,我們依然會(huì)碰到很多問(wèn)題。以三節(jié)點(diǎn)集群為例,兩個(gè)從節(jié)點(diǎn)啟動(dòng)建索引,停止對(duì)所有請(qǐng)求的響應(yīng)。此時(shí),主節(jié)點(diǎn)沒(méi)有足夠法定個(gè)數(shù),進(jìn)而轉(zhuǎn)化為從節(jié)點(diǎn)狀態(tài),整個(gè)集群此時(shí)就完了。基于命令行觸發(fā)的默認(rèn)的建索引都是在前臺(tái)建索引,這產(chǎn)生了普遍性的問(wèn)題。在未來(lái)的發(fā)行版中,希望能默認(rèn)后臺(tái)運(yùn)行。
一旦你觸發(fā)一個(gè)索引,簡(jiǎn)單的重啟服務(wù)并不能解決這個(gè)問(wèn)題,因?yàn)镸ongoDB會(huì)繼續(xù)重啟前的建索引的工作。如果之前你運(yùn)行后臺(tái)建索引任務(wù),在服務(wù)重啟后它會(huì)變成前臺(tái)運(yùn)行的任務(wù)。在這種情況下,重啟會(huì)讓問(wèn)題變得更糟糕。
如果你已經(jīng)啟動(dòng)了建索引的任務(wù),該如何停止它呢?幸運(yùn)的是,有方法相對(duì)簡(jiǎn)單的停止建索引任務(wù)。
選項(xiàng)一:殺掉建索引的進(jìn)程
使用db.currentOp()定位建索引進(jìn)程,然后使用db.killOp(<opid>)殺掉操作。建索引大致會(huì)是以下的樣子:
{ "opid" : 820659355, "active" : true, "lockType" : "write", .... "op" : "insert", "ns" : "xxxx", "query" : { }, "client" : "xxxx", "desc" : "conn", "msg" : "index: (2/3) btree bottom up 292168587/398486401 64%" }
如果正在建索引的節(jié)點(diǎn)不能響應(yīng)新連接,或者killOp不起作用,使用選項(xiàng)二。
選項(xiàng)二:配置“noIndexBuildRetry”并重啟
MongoDB提供了選項(xiàng)“noIndexBuildRetry”,它會(huì)指示MongoDB重啟后不再繼續(xù)沒(méi)建完的索引。
該參數(shù)并沒(méi)有直接出現(xiàn)在配置文件中,只是作為mongod進(jìn)程的參數(shù)。不推薦手工使用該參數(shù)運(yùn)行mongod,因?yàn)槿绻闩紶栆蕴囟ㄓ脩簦ㄈ鐁oot)運(yùn)行monogod進(jìn)程,它最終會(huì)改變所有文件的權(quán)限。一旦以root運(yùn)行,我們?cè)俅我詍ongod運(yùn)行時(shí),會(huì)遇到間歇性的問(wèn)題。
簡(jiǎn)單的做法是修改文件 /etc/init.d/mongo。查找下面這行:
OPTIONS=" -f $CONFIGFILE"
替換為以下內(nèi)容:
OPTIONS=" -f $CONFIGFILE --noIndexBuildRetry"
詳細(xì)步驟
為了討論,針對(duì)CentOS/RedHat/Amazon Linux提供了指令。
1.配置“-noIndexBuildRetry”
在所有數(shù)據(jù)節(jié)點(diǎn)中,增加“-noIndexBuildRetry”配置選項(xiàng)。
2.重啟所有建索引的節(jié)點(diǎn)
檢查每個(gè)數(shù)據(jù)服務(wù)的mongod日志文件,檢查是否在建索引。如果還在建,運(yùn)行命令“service mongod restrart”重啟服務(wù)。
3.刪除未完成的索引
一旦所有相關(guān)的節(jié)點(diǎn)都重啟,檢查所有索引列表,刪除掉列表中的未完成的索引。
4.移除“-noIndexBuildRetry”
修改文件(/etc/init.d/mongod),移除第一步添加的-noIndexBuildRetry配置選項(xiàng),這樣我們讓服務(wù)恢復(fù)到原來(lái)的默認(rèn)行為,即自動(dòng)繼續(xù)建索引。
祝建索引愉快!