在恰當的地方使用MongoDB的WriteConcern.SAFE參數

來源:互聯網
上載者:User

首先列一下WriteConcern的幾種拋出異常的層級參數:

  • WriteConcern.NONE:沒有異常拋出
  • WriteConcern.NORMAL:僅拋出網路錯誤異常,沒有伺服器錯誤異常
  • WriteConcern.SAFE:拋出網路錯誤異常、伺服器錯誤異常;並等待伺服器完成寫操作。
  • WriteConcern.MAJORITY: 拋出網路錯誤異常、伺服器錯誤異常;並等待一個主伺服器完成寫操作。
  • WriteConcern.FSYNC_SAFE: 拋出網路錯誤異常、伺服器錯誤異常;寫操作等待伺服器將資料重新整理到磁碟。
  • WriteConcern.JOURNAL_SAFE:拋出網路錯誤異常、伺服器錯誤異常;寫操作等待伺服器提交到磁碟的記錄檔。
  • WriteConcern.REPLICAS_SAFE:拋出網路錯誤異常、伺服器錯誤異常;等待至少2台伺服器完成寫操作。

 

當我們執行如下操作時(將"name"為"lily"的"age"設定為20):

db.update({"name":"lily"},{"$set":{"age":20}})

預設情況下,該操作會使用WriteConcern.NORMAL(僅在網路錯誤時拋出異常),等同於:

db.update({"name":"lily"},{"$set":{"age":20}},WriteConcern.NORMAL)

使用NORMAL模式參數,可以使得寫操作效率非常高。但是如果此時伺服器出錯,也不會返回錯誤給用戶端,而用戶端會誤認為操作成功。

因此在很多重要寫操作中需要使用WriteConcern.SAFE模式,保證可以感知到這個錯誤,保證用戶端和伺服器對一次操作的正確性認知保持一致。

(根據筆者測試,如果伺服器發生掉電情況,用戶端依然得不到當時操作的錯誤返回,需要特別注意)

另外在很多時候,我們需要確切知道這次寫操作是否成功(或者本次更新操作影響了多少個對象),這時候就需要:

WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});
if(ret.getN()>0) //操作影響的對象個數
return true;
else
return false;

或者:

WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});
if(ret.getLastError() == null)
return true;
else
return false;

此時,getLastError()會查詢上次操作結果是否出現錯誤。

更進一步

然後由於mongodb中使用串連池的原因,getLastError()需要再次從串連池中擷取串連,這樣效率會慢一些。可以這樣做:

db.requestStart();
WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});
if(ret.getLastError() == null)
return true;
else
return false;
db.requestDone();

就可以保證update操作和getLastError()使用同一個串連,並且減少了一次存/取串連的過程。

 

還有一個方法

此時也可以使用WriteConcern.SAFE參數:

WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}}, WriteConcern.SAFE);
if(ret.getLastError() == null)
return true;
else
return false;

// is equivalent to
db.requestStart();
WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});
if(ret.getLastError() == null)
return true;
else
return false;
db.requestDone();

這也是我推薦使用的方式,這樣即可以高效的得到返回結果,還能感知到伺服器錯誤,一舉兩得。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.