繁体   English   中英

MongoDB Java 中的提交和回滚事务

[英]Commit and Rollback transactions in MongoDB Java

目前,我正在使用以下代码:-

(我在代码中标出了重要的两行,这两行之间只是对现有文档的一些操作)

            clientSession.startTransaction();  // Important Line 1.
            Document walletDetailDoc = new Document("identifier", "walletBalanceDistribution");
            Document foundWalletDetailDoc1 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
            walletDetailDoc = new Document("identifier", to + "Backup");
            Document foundWalletDetailDoc2 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
            walletDetailDoc = new Document("identifier", from + "Backup");
            Document foundWalletDetailDoc3 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
            assert foundWalletDetailDoc1 != null;
            assert foundWalletDetailDoc2 != null;
            assert foundWalletDetailDoc3 != null;


            Bson updateWalletDoc = walletDetailDoc;
            Bson updateWalletDocOperation = new Document("$set", updateWalletDoc);
            walletDistributionCollection.updateOne(foundWalletDetailDoc1, updateWalletDocOperation);
            updateWalletDoc = new Document("identifier", "walletBalanceDistribution")
                    .append("totalRTKBalanceForPool", foundWalletDetailDoc2.get("totalRTKBalanceForPool"))
                    .append("lastCheckedBlockNumber", foundWalletDetailDoc2.get("lastCheckedBlockNumber"))
                    .append("lastCheckedTransactionIndex", foundWalletDetailDoc2.get("lastCheckedTransactionIndex"))
                    .append("balanceCollectedAsFees", foundWalletDetailDoc2.get("balanceCollectedAsFees"));
            updateWalletDocOperation = new Document("$set", updateWalletDoc);
            
            //////// TEMPORARY... TO BE REMOVED
            Thread.sleep(5000);
            clientSession.abortTransaction();  // Important Line 2
            boolean abc = true;
            if(abc) {
                return;
            }
            ////////

现在,我例外的是,一旦我调用abortTransaction() ,该集合将恢复为之前的 state ,就像在//Important Line 1之前一样。 但这并没有发生。 当我继续进行操作时,它们会保存在 MonogDB 中,并且不会在// Important line 2完成执行时恢复。

(以防万一,一切都在try catch并且任何行之间都没有错误。代码成功到达return语句。)

此外,如果需要,我正在使用以下 maven 依赖项:-

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.2.0</version>
</dependency>

如何正确地执行此操作,以便一切都完成,或者什么都不做(即回滚/中止)。

您需要在 session 事务中包含写操作,例如:

原装 state 合集:

 mongos> db.tra.find()
 { "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
 { "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }
 mongos> 

1 现在开始 session:

 session = db.getMongo().startSession()

2 现在您在启动的 session 中启动事务:

 mongos> session.startTransaction()

3 您将测试文档插入到事务中的集合中:

 mongos> session.getDatabase("test").tra.insert({a:"this will be aborted",today : new Date()})
 WriteResult({ "nInserted" : 1 })

4 现在检查集合,没有插入的文档(事务尚未提交):

 mongos> db.tra.find()
 { "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
 { "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }

5 现在中止事务:

 mongos> session.abortTransaction()

6 如您所见,没有插入任何内容(事务已中止):

 mongos> db.tra.find()
{ "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
{ "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }
mongos> 

当然,如果您将步骤 5 替换为 session.commitTransaction() 事务将被提交,您将看到应用于集合的操作。

这里有很好的 java 示例: https://www.mongodb.com/blog/post/java-and-mongodb-40-support-for-transaction

正确答案很简单...

(通过参考@R2D2 答案最底部的链接找到。)

(TL;DR:- 添加clientSession作为updateOne方法中的第一个参数)。

我们所要做的就是:-

        clientSession.startTransaction();  // Important Line 1.
        Document walletDetailDoc = new Document("identifier", "walletBalanceDistribution");
        Document foundWalletDetailDoc1 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
        walletDetailDoc = new Document("identifier", to + "Backup");
        Document foundWalletDetailDoc2 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
        walletDetailDoc = new Document("identifier", from + "Backup");
        Document foundWalletDetailDoc3 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
        assert foundWalletDetailDoc1 != null;
        assert foundWalletDetailDoc2 != null;
        assert foundWalletDetailDoc3 != null;


        Bson updateWalletDoc = walletDetailDoc;
        Bson updateWalletDocOperation = new Document("$set", updateWalletDoc);
        walletDistributionCollection.updateOne(clientSession, foundWalletDetailDoc1, updateWalletDocOperation);
        updateWalletDoc = new Document("identifier", "walletBalanceDistribution")
                .append("totalRTKBalanceForPool", foundWalletDetailDoc2.get("totalRTKBalanceForPool"))
                .append("lastCheckedBlockNumber", foundWalletDetailDoc2.get("lastCheckedBlockNumber"))
                .append("lastCheckedTransactionIndex", foundWalletDetailDoc2.get("lastCheckedTransactionIndex"))
                .append("balanceCollectedAsFees", foundWalletDetailDoc2.get("balanceCollectedAsFees"));
        updateWalletDocOperation = new Document("$set", updateWalletDoc);
        
        //////// TEMPORARY... TO BE REMOVED
        Thread.sleep(5000);
        clientSession.abortTransaction();  // Important Line 2
        boolean abc = true;
        if(abc) {
            return;
        }
        ////////

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM