如何在 mongodb 事务中测试翻转功能

Posted

技术标签:

【中文标题】如何在 mongodb 事务中测试翻转功能【英文标题】:How to test roll over feature in mongo db transactions 【发布时间】:2022-01-17 23:52:40 【问题描述】:

我是 MongoDB 的新手,我在我的一个应用程序中实现了事务功能,根据我的要求,我需要将数据保存到同一数据库中的不同集合中。下面是相同的代码sn-p

在 Tuple3 中,第一个元素是数据库,第二个元素是集合,第三个元素是我要保存的数据,它以 json 字符串的形式出现,我将其转换为 bson 文档

 ClientSession clientSession = mongoClient.startSession();
        try 
            clientSession.startTransaction(transactionOptions);
            for (Tuple3<String, String, String> value: insertValues) 
                MongoCollection<Document> collection = mongoClient
                        .getDatabase(insertValues.f0)
                        .getCollection(insertValues.f1);
                Document data= Document.parse(insertValues.f2);
                log.info(String.format("Inserting data into database %s and collection is %s", insertValues.f0, insertValues.f1));
                collection.insertOne(clientSession, data);
                clientSession.commitTransaction();
            
         catch (MongoCommandException | MongoWriteException exception) 
            clientSession.abortTransaction();
            log.error(String.format("Exception happened while inserting record into Mongo DB rolling back the transaction " +
                    "and cause of exception is: %s", exception));
         finally 
            clientSession.close();
        

以下是我正在使用的交易选项

 TransactionOptions transactionOptions = TransactionOptions.builder().readConcern(ReadConcern.LOCAL).writeConcern(WriteConcern.W1).build();

下面是带有 MongoClientOptions 的 MongoClient 方法,我将 Mongo DB 连接字符串作为该方法的输入

public MongoClient getTransactionConnection(String connectionString) 
    MongoClientOptions.Builder mongoClientOptions = new MongoClientOptions.Builder()
            .readConcern(ReadConcern.LOCAL)
            .writeConcern(WriteConcern.W1)
            .readPreference(ReadPreference.primary())
            .serverSelectionTimeout(120000)
            .maxWaitTime(120000)
            .connectionsPerHost(10)
            .connectTimeout(120000);

    MongoClientURI uri = new MongoClientURI(connectionString, mongoClientOptions);

    return new MongoClient(uri);

到这里为止就好了,它正在将数据插入到指定数据库下的三个不同的集合中。但是当我尝试一些负面情况时,我试图在 try 块中抛出异常,如果发生任何错误,理想情况下应该回滚该特定客户端会话的数据。

我试图通过使用计数变量来抛出异常,如果计数值等于 1,我将抛出异常,如果有任何数据写入数据库,则应该中止事务并回滚,但我看到的是写入其中一个集合并在停止程序之后引发异常,但实际上并没有回滚写入集合的数据。我在下面尝试这样的事情

ClientSession clientSession = mongoClient.startSession();
int count = 0;
            try 
                clientSession.startTransaction(transactionOptions);
                for (Tuple3<String, String, String> value: insertValues) 
                    MongoCollection<Document> collection = mongoClient
                            .getDatabase(insertValues.f0)
                            .getCollection(insertValues.f1);
                    Document data= Document.parse(insertValues.f2);
                    log.info(String.format("Inserting data into database %s and collection is %s", insertValues.f0, insertValues.f1));
                    collection.insertOne(clientSession, data);
                    if(count == 1)
                    throw new MongoException("Aborting transaction.....");
                
                count++;
                    clientSession.commitTransaction();
                
             catch (MongoCommandException | MongoWriteException exception) 
                clientSession.abortTransaction();
                log.error(String.format("Exception happened while inserting record into Mongo DB rolling back the transaction " +
                        "and cause of exception is: %s", exception));
             finally 
                clientSession.close();
            

我不确定我哪里出错了,我使用的是使用 Azure CosmosDB Api 部署的 Mongo DB 4.0 版。请提前帮我解决这个问题。

【问题讨论】:

【参考方案1】:

Cosmos DB 在单个集合的单个分区(分片)之外不支持事务。无论使用何种 API(在您的情况下为 MongoDB API),此限制都存在。这就是为什么您没有看到您所期望的行为。注意:这在Cosmos DB MongoDB compatibility docs中有所提及。

您需要提出自己的实现来管理应用内的数据一致性。

【讨论】:

以上是关于如何在 mongodb 事务中测试翻转功能的主要内容,如果未能解决你的问题,请参考以下文章

先锋事务高性能,王涛谈打造超越MongoDB的NoSQL

看门外汉如何实现:C#操作 MongoDB基本CURD的事务控制之 第二部分

CSDN----先锋事务高性能,王涛谈打造超越MongoDB的NoSQL

如何使用 Mongoose 使用 MongoDB 事务?

Docker 运行 MongoDB 副本集..,它是如何工作的?

如何在 JavaScript 中水平翻转图像