如何测试mongo db事务回滚

问题描述 投票:0回答:1

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

在 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。请帮助我解决这个问题,提前致谢。

java mongodb azure-cosmosdb azure-cosmosdb-mongoapi
1个回答
1
投票

Cosmos DB 在单个集合的单个分区(分片)之外不提供事务支持。无论使用何种 API(在您的情况下为 MongoDB API),此限制都存在。这就是为什么您没有看到预期行为的原因。注意:Cosmos DB MongoDB 兼容性文档中提到了这一点。

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

© www.soinside.com 2019 - 2024. All rights reserved.