ami*_*pra 3 transactions mongodb spring-boot
环境:
我们使用回调 API 来使用 MongoDB 事务。Core API 也会发生同样的情况。
样本:
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)
});
}
Run Code Online (Sandbox Code Playgroud)
错误:
com.mongodb.MongoCommandException:命令失败,错误 112(WriteConflict):'WriteConflict 错误:此操作与另一个操作冲突。请重试您的操作或多文档事务。” 在服务器 abc.mongodb.net:1234 上。完整响应为 { "errorLabels": [ "TransientTransactionError" ], "ok": 0, "errmsg": "WriteConflict 错误:此操作与另一个操作冲突。请重试您的操作或多文档事务。", "code ": 112, "codeName": "写入冲突"
查询:
我们已经将 MongoOperations/Template 与 ClientSession 关联起来。该会话打开了一个交易。但是,当代码使用 SessionScoped MongoOperations 时,它会失败,就好像它不知道打开的事务一样。
我们能不使用这种方法吗?
根据 交易主体中的https://docs.mongodb.com/v4.2/core/transactions-in-applications/中的示例 ,我们使用了 MongoClient 并且工作正常。我们可以不使用SessionScoped MongoTemplate吗?
所以,经过一番挖掘后,我认为这就是正在发生的事情......
对于数据库操作(命令,例如插入或更新),如果不在 ACID 事务中,冲突操作(示例中的第二个会话)将在当前操作提交后阻塞并重试。请记住,除了 ACID 事务外,MongoDB 还具有文档级原子性。
但是,对于多文档事务,行为有所不同。如果遇到 writeConflict,它会立即失败。该策略的设计方式是允许您的应用程序检测到这种情况,然后等待 X 毫秒并重试 N 次,其中 X 和 N 是您的舒适度。
您设置的参数与第二个会话将阻塞和等待多长时间无关,但与允许系统在建立锁定之前等待多长时间有关。默认值为 5 毫秒。您的示例显示 3 秒(3000 毫秒)。大概您指的是会话号 2 上的锁 - 您允许它获取锁所需的时间。问题在于,在尝试获取锁之前会检测到 writeConflict,因为在 ACID 事务中,预计应用程序而不是驱动程序执行等待。
| 归档时间: |
|
| 查看次数: |
9311 次 |
| 最近记录: |