我是 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。请帮助我解决这个问题,提前致谢。
Cosmos DB 在单个集合的单个分区(分片)之外不提供事务支持。无论使用何种 API(在您的情况下为 MongoDB API),此限制都存在。这就是为什么您没有看到预期行为的原因。注意:Cosmos DB MongoDB 兼容性文档中提到了这一点。
您需要提出自己的实现来管理应用程序内的数据一致性。