This bug affects 3.4 and although some code has changed in master, I believe it still exists in the same way. This ticket will reference the 3.4.4 code.
The bug is in the contract between a call from _applyOps to applyOperation_inlock for a non-upserting insert. If applyOperation_inlock is wrong, the return for other operations may need to be audited.
Consider a WriteConflictException (WCE) thrown in the collection->insert call here: https://github.com/mongodb/mongo/blob/r3.4.4/src/mongo/db/repl/oplog.cpp#L846-L861
In this case applyOperation_inlock is converting the WCE (which extends from DBException) into a Status with the appropriate code of 112 (WCE).
However the caller from _applyOps is anticipating WCE's to be thrown as it's wrapped in a WCE retry loop:
https://github.com/mongodb/mongo/blob/r3.4.4/src/mongo/db/catalog/apply_ops.cpp#L167-L177
The status with error code 112 increments the errors counter:
https://github.com/mongodb/mongo/blob/r3.4.4/src/mongo/db/catalog/apply_ops.cpp#L194-L197
Which results in the applyOps command returning ErrorCode: 8, UnknownError:
https://github.com/mongodb/mongo/blob/r3.4.4/src/mongo/db/catalog/apply_ops.cpp#L252-L254
As far as I know, engaging the retry loop in _applyOps would be correct behavior.
For interested parties, WCE's can (infrequently) be thrown on reads/writes other than concurrent access to the same document. These causes are usually memory pressure related.
- is related to
-
SERVER-23326 applyOps should use a single WriteUnitOfWork where possible
- Closed
-
SERVER-18982 Apply replicated inserts as inserts
- Closed
- related to
-
SERVER-30530 applyOps triggers invariant on WCE while applying upsert operations atomically
- Closed