Mongo Transaction doesnt rollback on WriteConcernError

I’m using pymongo and mongodb 4.4
when im start transaction as:
start_transaction(ReadConcern(“majority”),WriteConcern(“majority”), ReadPreference.PRIMARY, max_commit_time_ms=1)

1ms is experimental

Using this transaction i bulk_insert 1000 document to db, however pymongo gives 2 different exception time to time.

  1. pymongo.errors.WriteConcernError: operation exceeded time limit, full error: {'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}

In this error even tho it gives error and transaction abort, the data still written on database.

  1. pymongo.errors.ExecutionTimeout: operation exceeded time limit, full error: {'operationTime': Timestamp(1683746467, 1), 'ok': 0.0, 'errmsg': 'operation exceeded time limit', 'code': 50, 'codeName': 'MaxTimeMSExpired', '$clusterTime': {'clusterTime': Timestamp(1683746469, 999), 'signature': {'hash': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'keyId': 0}}}

In this error transaction aborts and no data written on disk.

My question is why i take different exceptions time to time even tho i do same task. And why 1. one do not do rollback?

This behavior is expected. WriteConcernError means that the commit succeeded on the primary but failed to replicate the commit with the configured writeConcern within the 1ms timeout. In this case your app can recover the state of the transaction by running session.commit_transaction() again.

The ExecutionTimeout error means that the server rejected the commit because it failed to succeed before the 1ms timeout. I believe the app can retry the session.commit_transaction() operation in this case as well but it’s possible the server automatically aborts the transaction in this case like you say (I’ll need to test this out to confirm the behavior here).

2 different exceptions are possible because the 1ms timeout is non-deterministic, in some cases the server may be able to commit the transaction in time, in other cases there might be resource contention which makes the commit take longer than 1ms.

The driver does not automatically retry the commit in either of these cases because these errors mean the configured timeout was exceeded.

Is this helpful?

2 Likes

Thanks for the answer Shane,

When i encounter with a error, i abort the transaction via pymongo. In WriteConcernError case even i abort the transaction, the data written into mongodb. Is this thing a case, because i was thinking transaction guarantees when an error occurs database will rollback the previous state.

Secondly, when i set transactionLifetimeLimitSeconds in mongo shell, it seems like its guarantees all the time when life time exceeds database rollback to previous state. Is there any mechanism difference between pymongo’s transaction.abort() and this admincommand?

db.adminCommand( { setParameter: 1, transactionLifetimeLimitSeconds: x } )

Transaction is rolled back only when unexpected things happen within a transaction context.

transactionLifetimeLimitSeconds controls the max time allowed for a transaction to process. So it is within a transaction context.

Write concern error means transaction it self succeeds, but replication fails to finish within the set timeout. So it’s replication context, and has nothing to do with your transaction operations.