知其然,知其所以然
MongoDB 2026-10-12

事务在 oplog 里长什么样

实测事务在 oplog 里的样子:提交的事务只写 1 条 applyOps 条目(op=c,ns=admin.$cmd),3 个操作装在里面,用 lsid + txnNumber + prevOpTime 链起来;不放进事务则每个操作一条;update 存 diff;提交标记在 config.transactions 的 state: committed;中止的事务不留痕迹;大事务拆成 partialTxn 加一条带 count 的最后条目。

MongoDB 事务 oplog applyOps partialTxn config.transactions 真实验证 动画演示
MongoDB 2026-10-12

change stream:resume token 与 oplog 的关系

实测 change stream 的 resume token:_data 是 83 字节的十六进制串,首字节 0x82 后 8 字节就是 clusterTime;用第 2 个事件的 token 恢复从第 3 个事件继续,不丢不重;空闲 stream 的 token 也随 oplog 前进;token 的位置不在节点的 oplog 窗口里(新成员 oplog 起点更晚)时恢复报 286 ChangeStreamHistoryLost。

MongoDB change stream resume token oplog ChangeStreamHistoryLost 真实验证 动画演示
MongoDB 2026-10-12

change stream 的过滤 pipeline 与 fullDocument

实测 change stream 的事件内容与过滤:update 默认只带 updateDescription;updateLookup 取到的是查询那一刻的文档,快速连续修改会丢掉中间状态;changeStreamPreAndPostImages 加 required 才有精确的前后镜像;pipeline 的 $match 在服务端过滤(10 个事件只收到 4 个);$project 不能去掉 _id;drop 后收到 invalidate。

MongoDB change stream fullDocument updateLookup 前后镜像 pipeline 真实验证 动画演示
MongoDB 2026-10-12

读关注:local、majority、snapshot 各读到什么

实测读关注 local、majority、snapshot、linearizable:健康时 local / majority / snapshot 都约 0.1 ms,linearizable 约 4.8 ms;构造“写入 primary 但未被多数确认”时 local 读到 NEW、majority 读到 old、linearizable 超时(code 50);恢复后 majority 也读到 NEW。

MongoDB 读关注 readConcern majority linearizable 副本集 真实验证 动画演示
MongoDB 2026-10-12

因果一致性会话

实测因果一致性会话:写 primary 后立刻读 secondary,不带会话 3000 次里有 2052 次读到旧值,带会话 0 次;用 stopReplProducer 让 secondary 落后,因果读阻塞约 3 秒直到追上;读命令里带 afterClusterTime;operationTime 可以手工在会话间传递,没有传递就没有保证。

MongoDB 因果一致性 causal consistency afterClusterTime 读写后一致 副本集 真实验证 动画演示
MongoDB 2026-10-12

游标:batchSize、getMore 与 10 分钟超时

实测游标:第一批 101 个、后续批次按 16 MiB 装(70,538 个);batch_size=10 读 10 万个文档要 10,001 条命令 944 ms,默认 3 条 54 ms;不带会话的游标空闲超时被回收(code 43),会话里的游标不受影响,noCursorTimeout 不会超时;遍历期间被修改的文档会被重复读到(1,500 次)。

MongoDB 游标 batchSize getMore cursorTimeoutMillis noCursorTimeout 真实验证 动画演示
MongoDB 2026-10-12

可重试写入:txnNumber 怎么避免重复执行

实测可重试写入:驱动重试带着同一个 lsid 和 txnNumber,计数器只加 1;服务端靠 oplog 条目上的 lsid / txnNumber / stmtId 去重,手写 OP_MSG 重发同一个请求返回 retriedStmtIds 而不再执行;insert 的整批重发只插入一次;update_many 不可重试;独立实例不支持事务号。

MongoDB 可重试写入 retryWrites txnNumber stmtId 幂等 真实验证 动画演示
MongoDB 2026-10-12

E11000 错误信息里有什么

实测 E11000 错误里的信息:code 11000、message 里的集合名 + 索引名 + dup key,以及 keyPattern 与 keyValue;单字段、复合、嵌套字段上的形状;同时违反两个唯一索引一次只报一个;长键在 message 里被截断而 keyValue 完整;批量与更新里的写法和“插入或取回”模式。

MongoDB E11000 重复键 唯一索引 keyPattern keyValue 真实验证 动画演示
MongoDB 2026-10-12

$set 一个字段,oplog 里存的是什么(diff 格式)

实测 $set 一个字段时 oplog 里存的是 diff:{$v: 2, diff: {u: …}},u 是新值、d 是删除、i 是新增、s<字段> 递归子文档与数组;$inc 记结果值;$pop 和 $pull 记整个数组;100 KB 文档改一个字段的 oplog 条目只有 165 字节,replace_one 要 100,157 字节;没有变化的 update 不写 oplog。

MongoDB oplog update diff 复制 $set 真实验证 动画演示
MongoDB 2026-10-12

initial sync:新节点加入时做了哪几步

实测新成员加入副本集的 initial sync:STARTUP → STARTUP2 → SECONDARY,121 MB 数据约 2.5 秒(logical 方式,约 1 秒复制完);replSetGetStatus 的 initialSyncStatus 给出进度字段;日志里的里程碑;同步期间的并发写入也会到齐,dbHash 一致;新成员的 oplog 从同步点开始。

MongoDB initial sync 副本集 新成员 STARTUP2 真实验证 动画演示
MongoDB 2026-10-12

复制延迟与 maxStalenessSeconds

实测复制延迟与 maxStalenessSeconds:健康时 0~2 秒;用 failpoint 让一个 secondary 停拉 oplog,延迟随时间线性增长到 95 秒;不设 maxStaleness 的 secondary 读 50 次有 19 次读到旧值,maxStalenessSeconds=90 的只有 1 次;下限 90 秒;放开后 3 秒追平。

MongoDB 复制延迟 maxStalenessSeconds secondary读 副本集 真实验证 动画演示
MongoDB 2026-10-12

rollback:没复制出去的写入去哪了

实测 rollback:旧 primary 上 w:1 写入的 5 个文档未复制就崩溃,新 primary 选出(10.6 s)后继续写入;旧 primary 重启后 SECONDARY→ROLLBACK→SECONDARY 约 0.5 秒,使用 recoverToStableTimestamp 方式;被回滚的文档保存在 dbpath/rollback/ 的 BSON 文件里,三个节点最终一致。

MongoDB rollback 回滚 副本集 w:1 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号