1. 程式人生 > >mongodb 建索引導致資料庫阻塞

mongodb 建索引導致資料庫阻塞

在MongoDB上建索引可能會對MongoDB叢集對可用性產生負面影響。在生產服務上,如果針對一個大集合觸發建立索引,且在前臺執行,你可能會發現,在索引建完之前,整個叢集都無影響。在一個大集合上,這個過程可能會持續幾個小時,甚至幾天。

解決的方法很簡單,MongoDB 提供了兩種建索引的訪問,一種是 background 方式,不需要長時間佔用寫鎖,另一種是非 background 方式,需要長時間佔用鎖。使用 background 方式就可以解決問題。 例如,為超大表 posts 建立索引, 千萬不用使用
複製程式碼 程式碼如下:
db.posts.ensureIndex({user_id: 1})

而應該使用
複製程式碼 程式碼如下:
db.posts.ensureIndex({user_id: 1}, {background: 1})

 

如果已經再建索引了,如何停止?

一旦你觸發一個索引,簡單的重啟服務並不能解決這個問題,因為MongoDB會繼續重啟前的建索引的工作。如果之前你執行後臺建索引任務,在服務重啟後它會變成前臺執行的任務。在這種情況下,重啟會讓問題變得更糟糕。

如果你已經啟動了建索引的任務,該如何停止它呢?幸運的是,有方法相對簡單的停止建索引任務。

選項一:殺掉建索引的程序

使用db.currentOp()定位建索引程序,然後使用db.killOp(<opid>)殺掉操作。建索引大致會是以下的樣子:
{ "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%" }


如果正在建索引的節點不能響應新連線,或者killOp不起作用,使用選項二。



選項二:配置“noIndexBuildRetry”並重啟

1. 重啟mongo 片的服務加上引數 

--noIndexBuildRetry                   don't retry any index builds that were 
                                        interrupted by shutdown

通過mongod --help 檢視此引數意義

2. 找到沒有建完的索引,刪除

3. 去掉noIndexBuildRetry   後重啟