簡體   English   中英

在單個事務中寫入兩個不同的 collections

[英]Writes to two different collections in a single transaction

我在我正在使用的應用程序中遇到了一個問題,在單個事務中我試圖更新一個集合中的文檔,並在創建它時在另一個文檔中使用更新的值,因為我添加了批量注冊第二個文件。

這會導致TransientTransactionErrorWriteConflict日志

到目前為止,這對單個文檔都有效,直到您嘗試再次重復該過程。

這可能嗎?

我嘗試使用不同的傳播級別,例如 REQUIRES_NEW 和 NESTED(不支持),但 oneUpdater.update() 方法沒有運氣,最初它是在沒有 @Transactional 的情況下實現的

@Document
class One { 
String id;
int value;
}

@Document
class Two {
String id;
String currentOneValue;
}

class OneUpdater{
 int update() {
  // searches for single document with the same id and increments value by 1
  return mongoTemplate.findAndmodify().getValue();
}
}

class Service {
private final OneUpdater oneUpdater; // uses mongoTemplate.findAndModify to increment value by 1
private final TwoRepository twoRepository; extends MongoRepository
    @Transactional
    void createTwo {
     int value  = oneUpdater.update();
     Two t = new Two(UUID.randomUuid.toString(), value);
     
    twoRepository.save(t);

    }

}
Caused by: com.mongodb.MongoCommandException: Command failed with error 112 (WriteConflict): 'WriteConflict error: this operation conflicted with another operation. Please retry your operation or multi-document transaction.' on server localhost:27017. The full response is {"errorLabels": ["TransientTransactionError"], "operationTime": {"$timestamp": {"t": 1651680481, "i": 2}}, "ok": 0.0, "errmsg": "WriteConflict error: this operation conflicted with another operation. Please retry your operation or multi-document transaction.", "code": 112, "codeName": "WriteConflict", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1651680481, "i": 2}}, "signature": {"hash": {"$binary": {"base64": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=", "subType": "00"}}, "keyId": 0}}}

那么 Mongo 已經給了你很好的建議或“......或多文檔交易”。

請參閱 Spring 配置 MongoTransactionManager 的示例https://spring.io/blog/2018/06/28/hands-on-mongodb-4-0-transactions-with-spring-data

在此示例中,操作恰好修改了 2 個文檔。

這個問題的解決方案比我想象的要簡單得多,Document One沒有存儲任何有意義的數據,而是支持Two提供一些額外的元數據。

我對這個問題的解決方案是用注釋update()方法

@Transactional(propagation = Propagation.NOT_SUPPORTED所以我的活動事務將被暫停,並且update()將以非事務方式執行,因為我不太關心那里的數據並且它停止拋出異常

class OneUpdater{
    @Transactional(propagation = Propagation.NOT_SUPPORTED
    int update() {
     // searches for single document with the same id and increments value by 1
     return mongoTemplate.findAndmodify().getValue();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM