How to fix TransientTransactionError in Shard Mongo DB with spring boot?

201 Views Asked by At

Scenario:

  1. I am using Mongo DB 6+ version with spring boot.
 @Bean
    MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }
 @Transactional
    public void save(Cart cart,Item item) {
        Cart cartFromDB = cartRepo.findById(cart.getId());
        if(cartFromDB!= null){
            cart.setId(cartFromDB.getId());
            cartRepo.save(cart);
        }else{
            cartRepo.save(cart);
        }
        itemRepo.save(item);
    }
  1. I am using @Transactional to save two different document in the same transaction.
  2. I was having Mongo DB with replica set, it worked fine without any error..
  3. Now Mongo DB has been changed to use sharding.
  4. I suspect after this change, I am getting TransientTransactionError intermittently. After couple of tries manually its getting succeeded
  5. When I implement retry it succeeded.

Error message:

com.mongodb.MongoCommandException: Command failed with error 13388 (StaleConfig): 'Transaction sd-ef6d-dsd-83bd-fsdfdf - dfdfdfdfdsdfdsfsd= - - :1 was aborted on statement 2 due to: an error from cluster data placement change :: caused by :: Encountered error from mongodb.cluster.local:26009 during a transaction :: caused by :: sharding status of collection mongodb.item is not currently known and needs to be recovered' on server mongos.xxxx.com:27017. The full response is {"ok": 0.0, "errmsg": "Transaction c43f42bd-ef6d-4c48-83bd-fgdfgsdfsgf - fgggeddddsksduydhdhsh= - - :1 was aborted on statement 2 due to: an error from cluster data placement change :: caused by :: Encountered error from mongodb.cluster.local:26009 during a transaction ::..... "errorLabels": ["TransientTransactionError"]}

Question:

1

There are 1 best solutions below

2
dododo On

TransientTransactionError is considered a possibly temporary and retryable error as mentioned here. So you may try to retry it manually in old style (see here) or better, and this way is recommended, to use a relatively new method: WithTransaction that handles retry logic behind the scene. I didn't work with spring-boot, so not sure how it can be called there, so you have to investigate it additionally