环境
我们使用回调API使用MongoDB事务。Core也是如此。
样本
private ThreadLocal<MongoOperations> sessionMongoTemplate;
try (final ClientSession session = getClientSession()) {
this.sessionMongoTemplate = ThreadLocal.withInitial(() -> getMongoOperations().withSession(session));
session.withTransaction(() -> {
// do some work
// call a method which does (sessionMongoTemplate.get().insert(entity);)
// (this throws WriteConflict Error)
});
}
误差
com.mongodb.MongoCommandException:命令失败,错误112 (WriteConflict):“WriteConflict错误:此操作与另一操作冲突。请重试您的操作或多文档事务。”在服务器abc.mongodb.net:1234上。完整的响应是{ "errorLabels":"TransientTransactionError“,"ok":0,"errmsg":"WriteConflict错误:此操作与其他操作冲突。请重试您的操作或多文档事务。”,“代码”:112,"codeName":"WriteConflict“。
查询:
我们已经将MongoOperation/模板与ClientSession联系起来了。那次会议打开了一个交易。但是,当代码使用SessionScoped MongoOperations时,它会失败,就好像它不知道打开的事务一样。
我们可以不采用这种方法吗?
,如事务体中的:https://docs.mongodb.com/v4.2/core/transactions-in-applications/中的示例所示,我们使用了MongoClient,它工作得很好。我们可以不使用SessionScoped MongoTemplate吗?
发布于 2021-09-24 17:42:10
所以,经过一番调查,我认为这是正在发生的.
对于数据库操作(命令,如insert或update),如果不是在ACID事务中,冲突操作(示例中的第二个会话)将阻止当前操作的提交,并进行重试。请记住,在ACID事务之外,MongoDB具有文档级原子性。
但是,对于多文档事务,行为是不同的。如果遇到一个writeConflict,它会立即失败。该策略是这样设计的,允许应用程序检测这种情况,然后等待X毫秒,然后重试N次,其中X和N是您的舒适级别。
您正在设置的参数与第二个会话阻塞和等待的时间无关,而是与允许系统等待多长时间才能建立锁有关。缺省值为5ms。你的例子显示了3秒(3000毫秒)。您大概是指第2号会话上的锁--您允许它花费多长时间才能获得一个锁。问题是在试图获取锁之前检测到了writeConflict,因为在ACID事务中,应用程序需要执行等待,而不是驱动程序。
https://stackoverflow.com/questions/69306723
复制相似问题