1. 程式人生 > 其它 >Mongo寫入安全機制

Mongo寫入安全機制

  寫入安全(Write Concern) 是一種客戶端設定,用於控制寫入的安全級別。預設況下,插入、刪除和更新都會一直等待資料庫響應(寫入是否成功),然後才會繼續執行。通常,遇到錯誤時,客戶端會丟擲一個異常(有些語言中可能不叫“異常”,不過實質上都是類似的東西)。

  有一些選項可以用於精確控制需要應用程式等待的內容。兩種最基本的寫入安全機制是應答式寫入(acknowledgedwirte)和非應答式寫入(unacknowledgedwrite)。應答式寫入是預設的方式:資料庫會給出響應,告訴你寫入操作是否成功執行。非應答式寫入不返回任何響應,所以無法知道寫入是否成功。

  通常來說,應用程式應該使用應答式寫入。但是,對於一些不是特別重要的資料 (比如日誌或者是批量載入資料),你可能不願意為了自己不關心的資料而等待資料庫響應。在這種情況下,可以使用非應答式寫入。

  儘管非應答式寫入不返回資料庫錯誤,但是這不代表應用程式不需要做錯誤檢查。如果嘗試向已經關閉的套接字(socket)執行寫入,或者寫入套接字時發生了錯誤,都會引起異常。

  使用非應答式寫入時,一種經常被忽視的錯誤是插入無效資料。比如,如果試圖插入兩個具有相同"_id"欄位的文件,shell就會丟擲異常:

>  db.foo.insert({"_id" : 1})
>  db.foo.insert({"_id" : 1})
E11000 duplicate key error index: test.foo.$_id_dup key: { : 1.0 }

  如果第二次插入時使用的是非應答式寫入,那麼第二次插入就不會丟擲異常。鍵重複異常是一種非常常見的錯誤,還有其他很多類似的錯誤,比如無效的修改器或者是磁碟空間不足等。

  shell與客戶端程式對非應答式寫入的實際支援並不一樣:shell在執行非應答式寫入 後,會檢查最後一個操作是否成功,然後才會向用戶輸出提示資訊。因此,如果在集合上執行了一系列無效操作,最後又執行了一個有效操作,shell並不會提示有錯誤發生。

>  db.foo.insert({"_id" : 1}); db.foo.insert({"id" : 1}); db.foo.count()
1

  可以呼叫getLastError手動強制在shell中進行檢查,這一操作會檢查最後一次 操作中的錯誤。

>  db.too.insert({"id" : 1}); db.foo.insert({"
_id" : 1}); print( ... db.getLastError()); db.foo.count() E11000 duplicate key error index: test.foo.$_id_ dup key: { : 1.0 } 1

  編寫需要在shell中執行的指令碼時,這是非常有用的。

  注意:2012年,預設的寫入安全機制改變了,所以,遺留程式碼的行為可能會與預期不一致。在此之前,預設的寫入是非應答式的。

  幸好,很容易得知當前程式碼是在預設的寫入安全機制發生變化之前寫的還是之後寫的:預設的寫入機制變為安全寫入之後,所有驅動程式都開始使用MongoClient這個類。如果程式使用的連線物件是Mongo或者Connection或者其他內容,那麼這段程式使用的就是舊的、預設不安全的API。在預設寫入安全機制發生變化之前,任何語言都沒有使用MongoClient作為類名,所以,如果你的程式碼使用了這個類名,說明你的程式碼是寫入安全的。

  如果使用的連線不是MongoCUent,應在必要時將舊程式碼中的非應答式寫入改成應答式寫入。