事务回滚根因是写关注未设{w:"majority"}、网络分区超10秒或oplog容量不足;需查optime倒挂、rs.status()状态、mongod.log中"rollback too large"等标记及system.profile中lsid/txnNumber链。

看日志里有没有“ROLLBACK”状态和optime倒挂
事务回滚发生后,rs.status() 输出中 stateStr 会短暂变成 ROLLBACK,但这只是表象。真正要盯的是各节点的 optime 和 lastAppliedWallTime 字段:如果某个节点的 optime 比新主节点还新,但 syncSourceHost 为空,说明它曾被网络隔离、自己继续写了数据,后来被强制回滚;这种“倒挂”是分叉写入的铁证。
查mongod.log里“rollback too large”或“not primary”连发
回滚触发时,日志里会出现明确标记:
-
rollback too large: XXX bytes→ 单次回滚超 300MB,节点卡在STARTUP2或RECOVERING,无法自动恢复 -
not master and slaveOk=false连续报错 → 主节点已宕机,客户端还在往旧地址发请求,说明故障已扩散到应用层 -
election started后紧接winning candidate→ 选举完成时间点,可对齐业务异常起始时间
别信rollback目录下的.bson文件能还原现场
/rollback/xxx/removed.2026-04-12T04-39-00.0.bson 这类路径只说明回滚已完成,不是诊断入口。这些文件是差量变更,没事务上下文,bsondump 出来也看不出哪条是哪个事务的哪一步。更关键的是:它们不包含 oplog 时间戳、不反映多数节点确认状态,人工比对极易误判。真正该查的是 system.profile 中带 lsid 和 txnNumber 的操作链——那里才有事务内真实执行顺序和耗时分布。
错误码 112 不等于“事务丢了”,得结合 errorLabels 看
驱动抛出 MongoServerError 且 error.code === 112 时,不能直接认定是提交失败。它可能是:
- 会话过期(
error.errorLabels含'TransientTransactionError')→ 可重试 - 写冲突被中止(实际是
WriteConflict,code 133,但某些路径下被包装成 112)→ 需检查是否开了retryWrites: true - oplog 截断导致事务上下文不可达 → 此时
rs.printSecondaryReplicationInfo()会显示从节点落后主节点超过 oplog 容量
事务回滚的根因永远不在 rollback 目录或错误码本身,而在写关注策略是否设为 {w: "majority"}、网络分区是否持续超 10 秒、以及 oplog 容量是否撑不住复制延迟——这三处漏掉任何一项,日志再全也救不回已发生的分叉。


















