• Mongodb的入门(8)mongodb事物分析


    老生常谈:<在前面博客中也介绍过>

      mongodb官网:https://docs.mongodb.com/manual/introduction/

      mongodb:官网上是这样定义的MongoDB is an open-source document database that provides high performance, high availability, and automatic scaling.翻译成中文:是一个开源文档数据库,提供高性能,高可用性和自动扩展。

          mongodb4:

         1  > MongoDB CTO Eliot Horowitz 刚刚于2月16日凌晨在MongoDB西雅图大会上宣布,MongoDB将在4.0版本中正式推出多文档ACID事务支持 。

                    2 >  “MongoDB 4.0 将支持多文档事务,届时MongoDB将成为唯一能够同时支持速度,灵活性,JSON文档模型优势和ACID数据完整性保证的数据库。通过快照隔离,(MongoDB)的事务能够提供一个全局一致的数据视图,

              并可以实现all-or-nothing的事务提交及回滚机制,保证数据的完整性。”

           3 >   这个功能的支持,完全不亚于2014年MongoDB引入WiredTiger存储引擎的影响力。因为这个功能的引入,原计划是3.8版本的MongoDB将直接进入4.0时代。

           4 > ACID 多文档事务,可以理解为关系型数据库的多行事务。在关系型的事务支持中,大家几乎无一例外支持同一事务内操作的原子性,即要么全部提交,要么全部回滚。这个同一事务内可以有多个操作,针对于多个表,或者是同一个表内的多行数据。

      注意:我在之前就介绍过mongodb以前也是有事务的,不过事物是在单文档操作上存在事务。现在介绍的是mongodb的多文档的原子事务


    介绍:

      mongodb 的事务是依靠 mongodb 连接的客户端 session 实现,事务执行的流程大致是 建立 session,通过 session startTransaction 启动事务,如果一系列事务都完成,那么 commitTransaction 完成事务操作,并结束当前事务 session;如果一系列事务中有任意事件失败, 那么  abortTransaction 中止事务,内部将已完成的任务回退到修改之前,并结束当前事务 session。

      

      事务和副本集(Replica Sets)

        副本集是 MongoDB 的一种主副节点架构,它使数据得到最大的可用性,避免单点故障引起的整个服务不能访问的情况的发生。目前 MongoDB 的多表事务操作仅支持在副本集上运行,想要在本地环境安装运行副本集可以借助一个工具包——run-rs,

        以下的文章中有详细的使用说明:https://thecodebarbarian.com/

      事务和会话(Sessions)

        事务和会话(Sessions)关联,一个会话同一时刻只能开启一个事务操作,当一个会话断开,这个会话中的事务也会结束。

      事务中的函数

    • Session.startTransaction()

        在当前会话中开始一次事务,事务开启后就可以开始进行数据操作。在事务中执行的数据操作是对外隔离的,也就是说事务中的操作是原子性的。

    • Session.commitTransaction()

        提交事务,将事务中对数据的修改进行保存,然后结束当前事务,一次事务在提交之前的数据操作对外都是不可见的。

    • Session.abortTransaction()

        中止当前的事务,并将事务中执行过的数据修改回滚。

      重试

        当事务运行中报错,catch 到的错误对象中会包含一个属性名为 errorLabels 的数组,当这个数组中包含以下2个元素的时候,代表我们可以重新发起相应的事务操作。

    • TransientTransactionError:出现在事务开启以及随后的数据操作阶段
    • UnknownTransactionCommitResult:出现在提交事务阶段

    mongo模拟事务实现:

      mongodb的多文档事务是基于副本集或者分片实现的,那我现在来简单再搭建一个mongo4 的副本集集群(大家还记得副本集和主从复制的区别吗?不知道的可以参考 Mongodb的入门(6)副本集 )

      下面我再搭建一下副本集,后期不会再搭建,请大家注意搭建步骤:

      第一步:创建一个mongodb副本集的文件夹:E:mongdb4

        在里面创建三个文件夹:分别是1688,1689,1690  这样我会把响应的端口号也设置成1688,1689,1690。

        

      第二步: 在每个文件夹下放入响应的mongodb服务。如果已经安装直接拷贝过来即可:

        

        注意。这步要做一下处理,因为你不是最新安装的,里面可能会有数据或日志。

         

       第三步:假设你已经处理好三个文件夹的文件,日志等数据都已经删除。环境已经干净。 

        下面我来做副本集:

          1》 创建是哪个文件夹来保存数据

            

          2> 分别进入各个bin下执行如下命令:

             mongod.exe --replSet shard1 --dbpath=E:mongdb4data1688 --port=1688

            mongod.exe --replSet shard1 --dbpath=E:mongdb4data1689 --port=1689

            mongod.exe --replSet shard1 --dbpath=E:mongdb4data1690 --port=1690

          执行之后会有:

            

       第四步:配置副本集

        任意进入一个bin下,连接到mongo上测试   mongo.exe  --port=1688 

          

         

          rsconf = {_id: "shard1", members: [ { _id: 0, host: "127.0.0.1:1688" } ] }
          rs.initiate( rsconf )
          rs.add("127.0.0.1:1689")
          rs.add("127.0.0.1:1690")

         到这副本集就配置完成了。再介绍几个命令用于维护副本集

          rs.isMaster();  查看是不是主节点

          rs.status();  查看副本集的状态。如下:

          

          

     


    springboot操作副本集:

       环境搭建,不介绍了,假设环境已经搭建好了。如:

         

      第一步:配置mongo连接信息:

         

      第二步测试:

            

       

    /**
         * @author huhy
         * @ClassName:SpringbootMongodb4ApplicationTests
         * @date 2018/11/23 11:26 
         * @Description: 测试事务
         */
        @Test
        public void testTro(){
            int a = 1000;
            //获取ClientSession
            ClientSession clientSession = mongoClient.startSession();
            Money yang = mongoTemplate.findById("12", Money.class);
            Money hui = mongoTemplate.findById("13", Money.class);
            int pay = yang.getPay()- a;
            hui.setPay(pay);
            yang.setPay(pay);
            try {
                //开启事务
                clientSession.startTransaction();
                //为mongoTemplate注入的事务特性
                MongoTemplate mongoTemplate = this.mongoTemplate.withSession(clientSession);
                mongoTemplate.save(hui);
                mongoTemplate.save(yang);
                if (pay < 0 ){
                    System.out.println("abortTransaction");
                    //撤销事务
                    clientSession.abortTransaction();
                }
            } catch (Exception e) {
                //提交事务
                clientSession.commitTransaction();
                e.printStackTrace();
            }
        }

    note:注意:springboot 操作mongo时候,要注意:有两种事务的特性:
        
    1》MongoTemplate mongoTemplate = this.mongoTemplate.withSession(clientSession);
    2》 在文档级别注入:
      

      我在这提醒一下大家。基于文档才是原生的,mongTemplate是为了方便我们使用才用的。

     3》有一部分基于mongo的注解在实体上,我就不贴出来了,有兴趣的可以自己搞一下。

  • 相关阅读:
    权限管理命令
    常用命令2
    常用命令1
    queue
    poj 3984
    L3-008 喊山 (30 分)
    常州大学新生寒假训练会试 I 合成反应
    dfs 的全排列
    poj 1154
    hdu 1241
  • 原文地址:https://www.cnblogs.com/huhongy/p/10007630.html
Copyright © 2020-2023  润新知