《MongoDB高手課》學習記錄(第十九天)

第十九天

今天要學習的章節是《22 | 事務開發:多文檔事務》,主要講解多文檔事務管理。shell

說明

  • MongoDB 在 4.2 開始全面支持了多文檔事務.
  • 對事務的使用原則應該是:能不用盡可能不用。
  • 經過合理地設計文檔模型,能夠規避絕大部分使用事務的必要性
  • 爲何?事務 = 鎖,節點協調,額外開銷,性能影響

MongoDB ACID 多文檔事務支持

  • Atomocity(原子性)
    單表單文檔 : 1.x 就支持,文檔中的字段要麼多更新,要麼不更新,不會出現一部分更新。
    複製集多表多行:4.0開始支持
    分片集羣多表多行:4.2開始支持
  • Consistency(一致性)
    writeConcern, readConcern (3.2版本開始支持)
  • Isolation(隔離性)
    readConcern (3.2版本開始支持)
  • Durability(持久性)
    Journal and Replication

事務的隔離級別

  • 事務完成前,事務外的操做對該事務所作的修改不可訪問
  • 若是事務內使用 {readConcern: 「snapshot」},則能夠達到可重複讀Repeatable Read

事務隔離

即事務內的變化沒提交前不影響事務外的數據數據庫

db.tx.insertMany([{ x: 1 }, { x: 2 }]);
var session = db.getMongo().startSession();
session.startTransaction();
var coll = session.getDatabase('test').getCollection("tx");
coll.updateOne({x: 1}, {$set: {y: 1}});
coll.findOne({x: 1}); // 返回 {x:1, y:1}
db.tx.findOne({x: 1}); // 返回 {x:1}
session.abortTransaction()

可重複讀

事務外雖然數據已經更新,在事務內結束前,讀取的數據一致是相同的。session

var session = db.getMongo().startSession();
session.startTransaction({
readConcern: {level: "snapshot"},
writeConcern: {w: "majority"}});
var coll = session.getDatabase('test').getCollection("tx");
coll.findOne({x: 1}); // 返回:{x: 1}
db.tx.updateOne({x: 1}, {$set: {y: 1}});
db.tx.findOne({x: 1}); // 返回:{x: 1, y: 1}
coll.findOne({x: 1}); // 返回:{x: 1}
session.abortTransaction();

事務寫機制

MongoDB 的事務錯誤處理機制不一樣於關係數據庫:性能

  • 當一個事務開始後,若是事務要修改的文檔在事務外部被修改過,則事務修改這個文檔時會觸發 Abort 錯誤,由於此時的修改衝突了;
  • 這種狀況下,只須要簡單地重作事務,也就是把事務停止了,從新開始;
  • 若是一個事務已經開始修改一個文檔,在事務之外嘗試修改同一個文檔,則事務之外的修改會等待事務完成才能繼續進行。

實驗:寫衝突

var session = db.getMongo().startSession();
session.startTransaction({ readConcern: {level: "snapshot"},
writeConcern: {w: "majority"}});
var coll = session.getDatabase('test').getCollection("tx");

繼續使用上個實驗的tx集合,開兩個 mongo shell 均執行下述語句
窗口1:
coll.updateOne({x: 1}, {$set: {y: 1}}); // 正常結束
窗口2:
coll.updateOne({x: 1}, {$set: {y: 2}}); // 異常 – 解決方案:重啓事務學習

實驗:寫衝突 (續)

窗口1:第一個事務,正常提交
coll.updateOne({x: 1}, {$set: {y: 1}});
窗口2:另外一個事務更新同一條數據,異常
coll.updateOne({x: 1}, {$set: {y: 2}});
窗口3:事務外更新,需等待
db.tx.updateOne({x: 1}, {$set: {y: 3}})設計

注意事項

  • 能夠實現和關係型數據庫相似的事務場景
  • 必須使用與 MongoDB 4.2 兼容的驅動;
  • 事務默認必須在 60 秒(可調)內完成,不然將被取消;
  • 涉及事務的分片不能使用仲裁節點;
  • 事務會影響 chunk 遷移效率。正在遷移的 chunk 也可能形成事務提交失敗(重試便可);
  • 多文檔事務中的讀操做必須使用主節點讀;
  • readConcern 只應該在事務級別設置,不能設置在每次讀寫操做上。
相關文章
相關標籤/搜索