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:\mongdb4\data\1688 --port=1688

        mongod.exe --replSet shard1 --dbpath=E:\mongdb4\data\1689 --port=1689

        mongod.exe --replSet shard1 --dbpath=E:\mongdb4\data\1690 --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的注解在實體上,我就不貼出來了,有興趣的可以自己搞一下。


免責聲明!

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



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