MongoDB - 事務


寫操作事務

writeConcern - w

writeConcern決定寫操作落到多少節點上才算成功,其取值包括:

  • 0:發起寫操作,不關心結果
  • n 1 <= n <= 集群最大數據節點數:寫操作復制到n個節點才算成功。
  • majority: 寫操作被復制到大多數節點才算成功
    發起寫操作的線程將阻塞到寫操作到達指定節點數才算成功;三節點復制集,默認是1,即主節點寫好了就成了; 對於重要數據設置w:majority,對於普通數據設置w:1

語法:
db.test.insert({count:1}, {writeConcern:{w:3,wtimeout:3000}})

journal - j

journal決定寫操作到什么程度才算成功

  • true: 寫操作落到journal文件中
  • false: 寫到內存就算成功

讀操作事務

讀數據,主要有兩個問題:

  • 從哪里讀?- readPreference
  • 什么樣的數據可以讀?(隔離性) - readConcern

readPreference

  • primary: 只從主節點讀
  • primaryPreferred:優先主節點
    🌰 用戶下單后轉到訂單詳情頁,可能從節點還沒有復制到新訂單
  • secondary: 只從從節點
    🌰 生成報表
  • secondaryPreferred: 從節點優先
    🌰 用戶查詢自己的歷史訂單
  • nearest: 選擇最近的節點
    🌰 用戶上傳的圖片分發到全世界

語法:
db.test.find({a:123}).readPref("secondary")

Tag

例如五節點復制集,三個硬件好一點的,打上tag"online",另外兩個打上tag"analyse",生成報表只選擇"analyse"節點,如圖所示:
tag示例

readConcern

這個節點上哪些數據是可以讀的:

  • available: 所有可用數據
  • local:所有可用且屬於當前分片
    local是默認值,在復制集上local和available無區別;只是在分片集上,當做chunk遷移時,只讀當前分片,否則把還沒遷移成功的另外個分片上遷移中的數據也讀出來
  • majority:大多數節點提交完成的數據
    實現方式:和MySQL的MVCC類似,節點上保存多個版本的數據,根據需求返回不同版本數據。使用majority可以有效避免“臟讀”。

首先,MongoDB對事務的支持更多指的是一個寫操作能否被持久化下來,所以“提交”的概念就是,寫到了多數節點(那么數據就不會丟失,永遠持久化了),在這個層面上,讀majority就不會“臟讀”,讀到的數據都是落到大多數節點的,而不會因為節點crash某個寫操作在讀之后丟失了(相當於回滾了)

  • linearizable:可線性化讀取文檔,保證該“讀”能讀到上一個“寫”,保證操作的線性順序
  • snapshot:讀取最近快照中的數據 (隔離級別最高,相當於serializable)

安全的讀寫分離

readConcern和writeConcern配合實現安全的讀寫分離
🌰用戶下單,並從從節點讀訂單數據:
不安全:

db.orders.insert({oid:100, sku:"kite", q:1})
db.orders.find({oid:100}).readPref("secondary")

安全:

db.orders.insert({oid:100, sku:"kite", q:1},{writeConcern:{w:"majority"}})
db.orders.find({oid:100}).readPref("secondary").readConcern("majority")

多文檔事務

mongoDB 4.2之后全面支持了多文檔事務,但是推薦還是能不用盡量不用,盡量通過合理的數據模型設計來規避事務的必要性。

語法:

try (ClientSession clientSession = client.startSession()) {
  clientSession.startTransaction();
  collection.insertOne(clientSession, docOne);
  collection.insertOne(clientSession, docTwo);
  clientSession.commitTransaction();
}

注意:

  • 多文檔事務的讀必須從主節點讀
  • 使用MongoDB4.2兼容的驅動
  • readConcern只應該在事務級別設置,不能在每次讀寫操作上


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM