首頁  >  問答  >  主體

mongodb使用find查詢所取得的遊標是否可以遍歷出查詢執行後的資料庫新增的記錄

mongodb使用find查詢傳回的遊標,是否可以遍歷出查詢執行後(記錄比較多查詢時間比較長,此時查詢還未執行完)資料表新增的記錄。
例如:
線程A在時間點t1使用find查詢資料表user傳回遊標,遍歷資料記錄。
線程B在時間點t2使用insert向資料表user插入記錄。
線程B在時間點t3執行完成。
線程A在時間點t4執行完成。
時間:t1 < t2 < t3 < t4
問:線程A是否可以查詢到線程B新增的記錄?

phpcn_u1582phpcn_u15822705 天前1004

全部回覆(2)我來回復

  • PHP中文网

    PHP中文网2017-04-24 16:02:18

    這是個非常好的問題,簡單說 MongoDB 不保證結果是否包含新文檔,因為它涉及多個文檔,甚至包括未來可能插入的文檔。在傳統資料庫中,可能讀到新插入的值,這一異常情況被稱為Phantom (幽靈),能滿足這一點的isolation (隔離、獨立) 等級是最高的serializable (可串行化),就是說例子中的一讀一寫兩組操作看起來好像是一先一後。用鎖機制實現的代價也非常高,效能也就比較差。參見這一論文。回到 MongoDB, MongoDB 以文件為單元,能夠保證文件層級的隔離,但是不保證多文檔間的作業的隔離(獨立),也就不支援事務,換來的是高效能。

    @huandu 說的沒錯,你測試時用 find().batchSize(2) 改成每批讀2個文檔,就會發現是可以讀到新加入的文檔的。預設的 batchSize 在 shell 裡是 20,可能就不容易觀察到了。別用 batchSize(1), 因為歷史原因它等於limit()。

    回覆
    0
  • 曾经蜡笔没有小新

    曾经蜡笔没有小新2017-04-24 16:02:18

    不一定。

    mongodb cursor 沒有隔離,可能會傳回更新後的資料。

    不過實際嘗試過程中發現,無論如何 insert,cursor 始終無法傳回新插入的資料。這可能是 mongodb 的實作細節,也可能在某些特殊情況下 cursor 才可以存取到新 insert 的數據,總之沒有文檔支持,不應該依賴這個行為。

    回覆
    0
  • 取消回覆