程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MongoDB數據庫 >> MongoDB綜合知識 >> mongodb 常見問題處理方法收集

mongodb 常見問題處理方法收集

編輯:MongoDB綜合知識

1 非正常關閉服務或關機後 mongod服務無法正常啟動

在使用中發現mongodb 的服務很容易因為非正常關閉而啟動不了,不過解決也很容易
刪除data目錄下的 *.lock文件,再運行下 /mongodb_binpath/mongod -repair -f config文件路徑 再啟動即可
也可以在/etc/init.d/mongod 服務啟動的文件中加入 啟動前刪除該文件 如下:

start() {
rm -f /usr/mongodb/data/master/mongod.lock
/usr/mongodb/bin/mongod --config /usr/mongodb/config/master.conf
}

2、server-side Javascript execution is disabled

完整信息:Javascript execution failed: group command failed: { "ok" : 0, "errmsg" : "server-side Javascript execution is disabled" }
解決方法:mongod.conf 這個配置文件裡 noscripting:false 如果true 就是禁止

3、 Decimal轉換成BsonValue值異常

BsonValue 暫不支持 Decimal類型,轉換前強制轉換類型,

if (type==typeof(Decimal))
{
return Convert.ToDouble(value);
}

如果用MongoDB,最好不要用decimal類型,否則在序列化的時候也有問題,可用double

4、MONGO Replica 頻繁插入大數據的問題

MONGO Replica 頻繁插入大數據的問題,當在復制集中頻繁插入大數據時有可能出現 “error RS102 too stale to catch up"出現這個錯誤的原因是SECONDARY即副節點的復制速度跟不上了,當需要批量頻繁向副本集中寫入數據時最好先移除副本節點,待插入完後重新同步。

5 Mongo集群沒有primary但有secondary時連接不上且不能讀數據

#mongodb默認是從主節點讀寫數據的,副本節點上不允許讀,需要設置副本節點可以讀。
shell
1 repset:SECONDARY> db.getMongo().setSlaveOk(); #要在primary上執行
2 rs.slaveOk()
其他客戶端
從secondary 讀數據
如果應用程序沒有設置相應的ReadReference也可能不能進行讀取操作

MongoClientSettings set = new MongoClientSettings();
List<MongoServerAddress> servers = new List<MongoServerAddress>();
servers.Add(new MongoServerAddress("192.168.129.129", 37017));
servers.Add(new MongoServerAddress("192.168.129.129", 37018));
servers.Add(new MongoServerAddress("192.168.129.129", 37019));
set.Servers = servers;

//設置副本集名稱
set.ReplicaSetName = "rs0";
//設置超時時間為3秒
set.ConnectTimeout = new TimeSpan(0, 0, 0, 3, 0);

MongoClient client = new MongoClient(set);
MongoServer server = client.GetServer();
MongoDatabase db = server.GetDatabase("test");
MongoCollection coll = db.GetCollection("test");

注:設置驅動的ReadReference也可以通過MongoDB連接字符串配置:mongodb://example1.com,example2.com,example3.com/?readPreference=secondary。通過連接字符串指定的read preference是針對整個連接。

set.ReadPreference = new ReadPreference(ReadPreferenceMode.PrimaryPreferred);
將ReadPreferenceMode設置成Secondary或SecondaryPreferred

下面是其他網友的補充:

一、
1. addshard 遇到的錯誤 db.runCommand({addshard:”172.16.5.104:20000″}) { “ok” : 0, “errmsg” : “can't use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual IPs host: 172.16.5.104:20000 isLocalHost:0″ } 遇到這樣的錯誤是由於某些服務啟動在 localhost 地址。 經過檢查發現 route 啟動時,讀取 config 服務是讀取的 localhost 地址: ./mongos –port 40000 –configdb localhost:30000 –fork [...]

1. addshard 遇到的錯誤

db.runCommand({addshard:”172.16.5.104:20000″})
{
“ok” : 0,
“errmsg” : “can't use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual IPs host: 172.16.5.104:20000 isLocalHost:0″
}

遇到這樣的錯誤是由於某些服務啟動在 localhost 地址。
經過檢查發現 route 啟動時,讀取 config 服務是讀取的 localhost 地址:

./mongos –port 40000 –configdb localhost:30000 –fork –logpath /data/route/log/route.log –chunkSize 1

將 localhost 修改為 IP 地址,問題解決。

2. 為什麼要同時有 config 和 route

一開始看到 config 和 route 的邏輯結構有一點疑惑。既然一個數據庫查詢的過程是:

客戶端
|
route
|
config
|
Database

而 config 的作用就是告訴 route 應該去哪一個 Database 取數據。那麼為什麼不能直接由客戶端向 config 發起請求呢?這時 route 的存在豈不是多余?
簡單的思考之後,得出了以下結論:

在有多個 route 和多個 config 的情況下,route 與 route 之間是平行的存在,也就是說,一個 route 並不知道另外一個 route 的存在。但是一個 route 知道所有 config 的存在。
那麼當要寫入數據時,只要你是通過了 route,route 就會通知到所有的 config,那麼每一個 config 便會知道數據是如何分片的。
如果將 route 這層去掉,那麼 config 與 config 之間並不知道彼此的存在。客戶端的請求很可能會只發向其中的一個 config,那麼也只有這一個 config 知道最新的分片狀態。

這個答案其實經不起太多的推敲,比如:

config 是可以從客戶端那裡拿到所有 config 的列表的,一旦有了列表之後,config 就可以彼此相互通信了。可以解決數據同步的問題。

我還要看多一些文檔。

3. Replica Set 啟動順序
在啟動兩個 rs 機器時,我先啟動了 second,後啟動了 Primary。這是一台機器上顯示自己為 second,另外一台為 unreachable。而另外一台機器顯示兩台機器均在 second。

這個現象需要驗證,是否 Replica Set 是有啟動順序限制。

二、

昨天到今天一直在嘗試在同一台機器上用多個IP地址來創建 Replica Set + Shard。 由於 MongoDB 官方用戶驗證方面的文檔說的也不太細。所以走了一些回頭路。 下面整理一些常見的錯誤,以及他們可能表達的意思。描述的順序是按照排錯的邏輯: 1. route 啟動的時候,連接 config 不可以以 localhost 為地址鏈接。不然會遇到以下錯誤: “errmsg” : “can't use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual IPs host: 172.16.5.104:20000 isLocalHost:0″ 2. 如果不以 localhost 為地址鏈接,那麼 config 啟動的時候不能加 –auth 選項,不然會在log文件中遇到以下錯誤: ERROR: [...]

昨天到今天一直在嘗試在同一台機器上用多個IP地址來創建 Replica Set + Shard。
由於 MongoDB 官方用戶驗證方面的文檔說的也不太細。所以走了一些回頭路。
下面整理一些常見的錯誤,以及他們可能表達的意思。描述的順序是按照排錯的邏輯:

1. route 啟動的時候,連接 config 不可以以 localhost 為地址鏈接。不然會遇到以下錯誤:

“errmsg” : “can't use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual IPs host: 172.16.5.104:20000 isLocalHost:0″

2. 如果不以 localhost 為地址鏈接,那麼 config 啟動的時候不能加 –auth 選項,不然會在log文件中遇到以下錯誤:

ERROR: config servers not in sync! not authorized, did you start with –keyFile?

此時進程無法啟動

3.在 route 和 config 准備完畢後,通過 route 以遠程 IP 為地址添加shard,則報錯:(有 –auth 參數)

db.runCommand({addshard:'a1:28010′})
{
“ok” : 0,
“errmsg” : “failed listing a1:28010′s databases:{ errmsg: \”need to login\”, ok: 0.0 }”
}

4. 去掉 –auth 參數,添加 shard,成功!

5. 依舊保留 –auth 參數,添加用戶後,再添加shard。報錯:

“errmsg” : “couldn't connect to new shard DBClientBase::findN: transport error: a1:28010 query: { getlasterror: 1 }”

總結:MongoDB 2.0 的認證方式

1.Replica Set 之間通過 key 來相互認證。
2.Route 與 Config 之間不存在認證關系,Route 連接 Config 時不能以 localhost 連接。
3.單個Mongod進程啟動後,如果無 –auth 選項且無用戶,則必須通過 localhost 連接才能添加用戶和做其他操作。如果通過遠程(非127.0.0.1的IP地址)連接,則必須要輸入用戶名、密碼。此時如果還無用戶存在,則無法連接。
4.添加 Shard 時,mongod 不可以帶 –auth 參數,不然會添加失敗。

三、

續上篇 筆記2 ,還是說一下關於 MongoDB 認證的問題。 在 王文龍 所寫的 《MongoDB 實戰》 中,寫到: 創建主從 key 文件,用於標識集群的私鑰的完整路徑,如果各個實例的 key file 內容不一 致,程序將不能正常用。 我誤以為 –keyFile 是各個節點之間的認證方式。其實不是的。各個節點之間的確認關系參數是 –replSet。只要此參數後面的內容一致。Replica Set 就可以創建成功。 在官方文檔中提到: You do not need to use the –auth option, too (although there's no harm in doing so), –keyFile implies –auth. –auth does not imply –keyFile. 也就是說 keyFile 其實包含了 auth 的作用。 [...]

續上篇 筆記2 ,還是說一下關於 MongoDB 認證的問題。
在 王文龍 所寫的 《MongoDB 實戰》 中,寫到:

創建主從 key 文件,用於標識集群的私鑰的完整路徑,如果各個實例的 key file 內容不一 致,程序將不能正常用。

我誤以為 –keyFile 是各個節點之間的認證方式。其實不是的。各個節點之間的確認關系參數是 –replSet。只要此參數後面的內容一致。Replica Set 就可以創建成功。

在官方文檔中提到:

You do not need to use the –auth option, too (although there's no harm in doing so), –keyFile implies –auth. –auth does not imply –keyFile.

也就是說 keyFile 其實包含了 auth 的作用。

而當你加了 –keyFile 參數後,如果你要添加 Shard,則會收到報錯:

need to login

這和加了 auth 的報錯一致。

以前沒接觸過 MongoDB,直接從 2.0 使用,所以裡面的有些細節可能還不理解。看到有人說 auth 是 2.0 的新功能。而之前只能用 keyFile 驗證。還不太清楚 keyFile 下用戶登陸的一些細節。

MongoDB 常見問題處理

       說明: 這裡的問題是我在看MongoDB官網文章時,從裡面總結出來的。
mongod process "disappeared":
           這個說的是mongodb進行消失,可以理解為死掉等。可以從下面中找問題在
               #grep mongod /var/log/messages
               #grep score /var/log/messages
Socket errors in sharded clusters and replica sets:
         echo 300 > /proc/sys/net/ipv4/tcp_keepalive_time 默認是7200
關於tomm many open files:
           First:檢查以下幾項:
          lsof | grep mongod
          lsof | grep mongod | grep TCP
          lsof | grep mongod | grep data | wc
       可以用:ulimit解決: ulimit -n X
High TCP Connection Count:
TCP Connection過大時,可以檢查是不是client apps使用連接池問題
Mongod (hard) connection limit
            這個連接數限制在20000,可以手動調整大小
Data files count with very large databases
            數據在T級以上時,確定是否做了限制(手動增加),再用repairdatabase時,會同時有2 copies
No space left on device
            這個時候reads仍然在進行,要做的是first shutdown servers, then to delete some      data and compact
     Checking Siez of a collection(檢查集合)
              >db.(collectionname).validate();
NUMA:
       Linu,
Numa and MongoDB不能很好的一起工作。如果機器在numa硬件運行的時候,需要把它關閉。一般出現大規模性能慢下來或一段時間cpu占用很高的system time 。可以從日志中抓取NUMA字。(我也翻譯不出這個NUMA是什麼意思)
關閉的方法:

一:在啟動mongoDB的時候:
                    numactl --interleave=all ${MONGODB_HOME}/bin/mongod --config conf/mongodb.conf

二:在不關閉mongoDB時:
                   echo 0 > /proc/sys/vm/zone_reclaim_mod
         案例:

http://www.jb51.net/article/109199.htm

或http://www.jb51.net/article/109198.htm

NFS:
            官網不建意采用NFS系統文件運行mongoDB,因為NFS版本問題會導致性能很低或無法工作
SSD:
          mongoDB在SSD(固態硬盤)運行很快,但是比RAM低。可以用mongoperf進行硬盤性能狀態分析。
Virtualization:
            mongoDB在虛擬化上運行的很好,如OpenVZ 兼容EC2 ,VMWare也可以但是clone的時候會出現一些問題由其在a member of a replica set(一個復制節點上),要想可用的,需要journaling處在可用狀態,再進行clone。如果沒有的開啟journaling的時候,stop m ongod ,clone, and tehn restart    
        注意:在MongoDB中要用IP地址不要使用機器名或localhost,不然會出現鏈接不數據庫的。
Journal(日志):
日志的開啟:--journal ;關閉:--nojournal ,默認時間是100ms
              啟動時會在數據目錄下創建一個journal地文件目錄,在受到毀壞時,再啟動mongoDB不需要再運行repair,它會自動恢復的。
               可以通過運行journalLatencyTest測試寫入磁盤的性能和同步性能。
                >use admin
                >db.runCommand("journalLatencyTest")
Backup with --journal 中journal是支持回滾恢復。
journaling的時候,stop m ongod ,clone, and tehn restart    
        注意:在MongoDB中要用IP地址不要使用機器名或localhost,不然會出現鏈接不數據庫的。
The Linux Out of Memory OOM Killer:

情況一:

Feb 13 04:33:23 hostm1 kernel: [279318.262555] mongod invoked oom-killer: gfp_mask=0x1201d2, order=0, oomkilladj=0
    這是因為內存溢出導致mongodb進程被剎死
 
情況二:

   內在沒有溢出,能過db..serverStatus()或mongostat查看內存virtualbytes - mappedbytes的界限
  
情況三:

    ulimit的限制
t:minor-latin; mso-fareast-font-family:宋體;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family: Calibri;mso-hansi-theme-font:minor-latin'>中journal是支持回滾恢復。
journaling的時候,stop m ongod ,clone, and tehn restart    
        注意:在MongoDB中要用IP地址不要使用機器名或localhost,不然會出現鏈接不數據庫的。

mongodb占用空間過大的原因,在官方的FAQ中,提到有如下幾個方面:
 1、空間的預分配:為避免形成過多的硬盤碎片,mongodb每次空間不足時都會申請生成一大塊的硬盤空間,而且申請的量從64M、128M、256M那樣的指數遞增,直到2G為單個文件的最大體積。隨著數據量的增加,你可以在其數據目錄裡看到這些整塊生成容量不斷遞增的文件。
         2、字段名所占用的空間:為了保持每個記錄內的結構信息用於查詢,mongodb需要把每個字段的key-value都以BSON的形式存儲,如果value域相對於key域並不大,比如存放數值型的數據,則數據的overhead是最大的。一種減少空間占用的方法是把字段名盡量取短一些,這樣占用空間就小了,但這就要求在易讀性與空間占用上作為權衡了。我曾建議作者把字段名作個index,每個字段名用一個字節表示,這樣就不用擔心字段名取多長了。但作者的擔憂也不無道理,這種索引方式需要每次查詢得到結果後把索引值跟原值作一個替換,再發送到客戶端,這個替換也是挺耗費時間的。現在的實現算是拿空間來換取時間吧。
         3、刪除記錄不釋放空間:這很容易理解,為避免記錄刪除後的數據的大規模挪動,原記錄空間不刪除,只標記“已刪除”即可,以後還可以重復利用。
RepairDatabase命令:
  數據庫總會出現問題的,關於修復的方法如下:
運行db.repairDatabase()來整理記錄,但這個過程會比較緩慢。
當MongoDB做的是副本集群時:可以直接把數據rm掉,然後再重新啟動。
       當在不是primariy server上運行時,會得到一個"clone failed for wkgbc with error: query failed wkgbc.system.namespaces"
 解決方法:為了修復,需要restart server 不加--replSet選項並且要選用不同的端口
LINUX下找出哪個進程造成的IO等待很高的方法:

       可以判斷是不是IO問題造成的:
   
          #/etc/init.d/syslog stop
          #echo 1 > /proc/sys/vm/block_dump
          #dmesg |egrep "READ|WRITE|dirtied"|egrep -o '([a-zA-Z*])'|sort|uniq -c|sort -rn|head
   
下面是從網上找的案例:

昨天我訪問mongodb的python程序開始出錯,經常拋出AssertionError異常,經查證只是master查詢異常,slave正常,可判斷為master的數據出了問題。

修復過程:

1、在master做db.repairDatabase(),不起作用; 這個時間很長
2、停止slave的同步;
3、對slave作mongodump,備份數據;
4、對master作mongostore,把備份數據恢復,使用–drop參數可以先把原表刪除。
5、恢復slave的同步。

實例二:碎片整理-replSet架構

1、rs.freeze(60)    在60s內該機器無法成為primary
2、在primary機上進行rs.stepDown([120]) 讓該機器成為從節點且在120s內不會成為primary
3、在primary上 ,可以將data的數據刪掉 ,啟動。數據會自動兩步上去的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved