MongoDB提供了寫關注,用來描述數據庫寫操做返回信息的保證級別。寫關注的強度決定了保證的級別。當插入,更新,刪除是弱寫關注的時候,操做返回的速度則快。若是寫關注是弱的,在一些寫失敗的時候,寫操做可能不會持久。寫關注級別越強,客戶端則須要越長的時間來等待MongoDB確認寫操做。mongodb
MongoDB提供了不一樣的寫關注的級別來更好的知足不一樣應用程序的需求。在一個實際的MongoDB部署中,客戶端須要調整寫關注的級別來確保重要寫操做的持久性。對於其餘一些不那麼重要的寫操做,客戶端須要調整到弱寫關注來保證更好的性能。數據庫
MongoDB定義了以下四種寫關注級別,依次從弱到強:網絡
實際應用中通常是在Client Driver裏設置寫關注的,它和db.getLastError()方法關係很大。通常來講,Mongo Driver在執行一個寫操做(insert,update,delete)以後,都會馬上調用db.getLastError()命令。這樣纔有機會知道剛纔的寫操做是否成功,若是捕獲到錯誤,就能夠進行相應的處理。MongoDB Server並不關心錯誤,只負責通知Client發生了錯誤。app
這裏有2點須要注意:函數
在這種寫關注級別時,MongoDB馬上返回結果,而後執行寫入操做,相似於忽略寫錯誤。然而,驅動程序會去接收和處理網絡錯誤。因此getLastError()的返回值必定是null,即便以後的Apply發生了錯誤,Driver也不知道。使用這個級別的Write Concern,Driver的寫入調用馬上返回,因此性能是最好的,可是可靠性是最差的,所以並不推薦使用。在各平臺最新版本的Driver中,也再也不以0做爲默認級別。其實還有一個w:-1的級別,是error ignored,基本上和w:0差很少。區別在於,w:-1不會捕獲任何錯誤,而w:0能夠捕獲network error。性能
在這種寫關注級別時,mongod確認寫操做,而且在內存視圖上完成數據改變。它容許客戶端捕獲網絡,重複鍵等其它錯誤。和Unacknowledged的區別是,如今MongoDB只有在Apply(實際寫入操做)完成以後,纔會返回getLastError()的響應。因此若是寫入時發生錯誤,Driver就能捕獲到,並進行處理。這個級別的Write Concern具有基本可靠性。可是Acknowledged級別的寫關注並不確保數據已經持久化到系統硬盤,它是MongoDB默認的寫關注級別。日誌
Acknowledged級別的Write Concern也不是絕對可靠的。由於MongoDB的Apply操做是將數據寫入內存,按期經過fsync寫入硬盤。若是在Apply以後,fsync以前mongod掛了,或者甚至Server掛了,那持久化其實是失敗的。可是在w:1的級別下,Driver沒法捕獲到這種狀況下的error,由於response在Apply以後就已經返回到Driver。MongoDB解決這個問題的辦法是使用Journal機制,寫操做在寫入內存以後,還會寫到journal文件中,這樣若是mongod非正常down掉,重啓之後就能夠根據journal文件中的內容,來還原寫操做。code
在Driver層面,則是除了設置w:1以外,再設置journal:true或j:true,來捕獲這個狀況下的error。在這種關注級別下,MongoDB能確保寫操做將數據提交到了 journal
日誌。這種寫關注能保證MongoDB崩潰後恢復數據。固然,前提是你必須開啓journal
日誌功能。但這樣寫操做必須等到下一第二天志提交才返回結果,爲了減小操做延遲,要提升日誌提交的頻率配置。server
這個寫關注級別下,只有Secondary從Primary完成了複製以後,getLastError()的結果纔會返回。也能夠同時設置journal:true或j:true,則還要等journal寫入也成功後纔會返回。可是注意,只要Primary的journal寫入就會返回,而不須要等待Secondary的journal也寫入。相似的也能夠設置w:3,表示至少要有3個節點有數據;或者w:majority,表示>1/2的節點有數據。通常小規模的集羣就是3節點部署,因此配置w:2就能夠了。內存
設置Write Concern級別,其實就是在寫操做的性能和可靠性之間作權衡。寫操做的等待時間越長,可靠性就越好。對於非關鍵數據,建議使用默認的w:1就能夠了,對於關鍵數據,則使用w:1 & j:true比較好。這裏要注意,journal不管如何都是建議打開的,設置j:true,只是說Driver調用getLastError()以後是否要等待journal寫入完成再返回。並非說不設置j:true就關閉了server端的journal。
通常來講,開發者寫的代碼,不須要自行調用db.getLastError()函數,Driver在每個寫操做以後,都會馬上自動調用該方法。
db.collection("test", {}, function(err, collection) { collection.insert({ name: "world peace" }, function(err, result) { assert.equal(null, err); console.log(result); db.close(); }) });
這段代碼,driver在insert()以後,隱式調用db.getLastError(),若是捕獲到任何錯誤,就會賦給回調函數中的err參數。區別就在因而否可以捕獲到錯誤。在w:-1時,err永遠是null(沒有機會捕獲到error);在w:0時,通常也捕獲不到,除了network error;在w:1時,若是mongod apply發生錯誤,就會傳遞給err參數了。代碼都是同樣的,區別就在於設置的Write Concern級別。詳細的說明請參考http://docs.mongodb.org/manual/reference/command/getLastError/。