zoukankan      html  css  js  c++  java
  • MongoDB入门实战教程(12)

    MongoDB在4.2版本开始全面支持了多文档事务,这也让MongoDB可以作为OLTP的选项之一,本篇我们就来学习一下MongoDB的多文档事务。

    1 ACID支持程度

    谈到事务,就不得不提经典的ACID特性,MongoDB对ACID的支持程度到底如何呢?且看下表:

    事务属性 支持程度
    Atomocity 原子性 单表单文档:1.x 就开始支持
    复制集多表多行:4.0 开始支持
    分片集多表多行:4.2 开始支持
    Consistency 一致性 writeConcern, readConcern
    Isolation 隔离性 readConcern
    Durability 持久性 Journal and Replication

    2 多文档事务使用方法

    基本使用方式

    MongoDB多文档事务的使用方式与关系型数据库基本类似。

    但是需要注意的是:多文档事务只能应用在副本集 或 mongos 节点上。如果你只是一个单点的mongo实例,是无法进行多文档事务实践的。

    如何搭建一个mongodb的复制集?参考《MongoDB入门实战教程(2)

    在Mongo Shell中的实践

    下面演示了如何通过Mongo Shell来进行一个多文档操作的事务提交:

    var session = db.getMongo().startSession();
    session.startTransaction({readConcern: { level: 'majority' },writeConcern: { w: 'majority' }});
    
    var coll1 = session.getDatabase('students').getCollection('teams');
    coll1.update({name: 'yzw-football-team'}, {$set: {members: 20}});
    
    var coll2 = session.getDatabase('students').getCollection('records');
    coll1.update({name: 'Edison'}, {$set: {gender: 'Female'}});
    
    // 成功提交事务
    session.commitTransaction();
    
    // 失败事务回滚
    session.abortTransaction();

    在.NET Driver中的实践

    using (var clientSession = mongoClient.StartSession())
    {
        try
        {
            var contacts = clientSession.Client.GetDatabase("testDB").GetCollection<Contact>("contacts");
            contacts.ReplaceOne(contact => contact.Id == "1234455", contact);
            var books = clientSession.Client.GetDatabase("testDB").GetCollection<Book>("books");
            books.DeleteOne(book => book.Id == "1234455");
    
            clientSession.CommitTransaction();
        }
        catch (Exception ex)
        {
            // to do some logging
            clientSession.AbortTransaction();
        }
    }

    在Java Driver中的实践

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

    扩展:事务的隔离级别

    关于MongoDB的事务隔离级别,有以下亮点说明:

    (1)默认情况下,在MongoDB的事务完成前,事务外的操作对该事务所做的修改是访问不到的

    (2)如果我们在开启事务时设置 {readConcern: "snapshot"},则可以达到可重复读(Repeatable Read)的级别,这也是MySQL的默认事务隔离级别。而如果我们设置{readConcern: "majority"},则可以达到读提交(Read Commited)的级别,这是MSSQL的默认事务隔离级别。

    3 注意事项

    MongoDB可以实现和关系型数据库类似的事务场景,但在应用程序开发的时候必须使用与4.2及以上版本兼容的Driver。

    事务默认必须在60s内完成,否则将被取消。当然,我们也可以调整这个默认值,但是建议不要超过60s。

    多文档事务中的读操作必须使用主节点读取,这是为了保证事务的数据强一致性。

    虽然,MongoDB在4.2版本开始全面支持多文档事务,但是并不代表我们可以毫无节制地使用它。相反,对事务的使用原则应该是:能不用尽量不用

    通过合理地设计文档模型,其实可以规避绝大部分使用事务的必要性。

    Why?因为 事务 = 锁,节点协调,额外开销,性能影响 ...

    4 总结

    本文简单介绍了MongoDB多文档事务的使用,它弥补了MongoDB无法实现传统关系型数据库ACID特性的不足。

    下一篇,我们会学习MongoDB的分片集原理 及 分片策略。

    参考资料

    唐建法,《MongoDB高手课》(极客时间)

    郭远威,《MongoDB实战指南》(图书)

    △推荐订阅学习

  • 相关阅读:
    redis分布式锁原理
    设置linux源
    linux 设置固定ip 并且解决ping www.baidu.com不通问题
    java内存模型
    Messenger和MVVM中的View Services
    MVVMLight
    MVVMLight
    MvvmLight
    MVVM 事件转命令1
    Mvvm简介
  • 原文地址:https://www.cnblogs.com/edisonchou/p/mongodb_learning_summary_part12.html
Copyright © 2011-2022 走看看