-
Type: Spec Change
-
Resolution: Unresolved
-
Priority: Major - P3
-
None
-
Component/s: Retryability
-
None
-
Needed
In PYTHON-1650, a user discovered a bug in PyMongo's implementation of retryable writes where it was possible for both the initial retryable write attempt and the retry attempt to never increment the txnNumber. Worse, this could occur when a primary was shut down normally. Testing retryable writes against real shut down scenarios (shutdowns, crashes, stepdowns) would have caught this issue.
The specific scenario where PyMongo's bug would be hit is when:
- Primary shuts down.
- Client initiates a retryable write, retryWrites=true, and the server is 3.6 or 4.0.
- Server selection succeeds on the stale primary yielding server P.
- Socket is checked out of P's pool.
- The pool notices the socket has been closed (because this socket has been idle for >1 second) and attempts to create a new connection to the old primary.
- The connection attempt fails with a (retryable) "connection refused" error because the old primary is not running.
- The initial write attempt fails with a retryable error before incrementing the txnNumber.
- The retry attempt waits until the new primary is elected, does not increment the txnNumber, and runs the write with a previous txnNumber.
The fix implemented in PyMongo 3.7.2 is to always increment the txnNumber before server/socket selection (similar to how start_transaction works).
Note that it would be much less likely for this to occur if PYTHON-1435 was implemented because server selection would wait for the new primary on the initial attempt.
- is related to
-
DRIVERS-2121 Test retryable reads against live failover scenarios
- Backlog
- related to
-
PYTHON-1650 Replica failover with retryWrites not always working
- Closed