MongoDB事务仅保障写操作原子性与隔离性,不提升普通查询一致性;因果一致性需显式启用会话并配合readConcern:"majority"与writeConcern:{w:"majority"}才能生效,且仅保证单一会话内读写逻辑顺序。

事务不能提升普通查询的一致性
MongoDB 事务只对写操作(insert、update、delete)提供原子性和隔离性,对只读查询(find、aggregate)本身不施加事务级一致性约束。开启事务后执行的 find,默认仍可能读到其他会话未提交的写入(取决于隔离级别),或因主从延迟读到过期数据。事务不是“让所有查询变强一致”的开关。
Causal Consistency 依赖会话和读写操作链
因果一致性不是独立开关,它必须配合 startSession() + 显式启用 + 后续带 readConcern: "majority" 和 writeConcern: {w: "majority"} 的操作才能生效。常见错误是只调用 startSession() 却没在读/写命令中传参,或漏配 readConcern,导致因果链实际未建立。
- 必须使用同一个
ClientSession对象贯穿读-写-再读流程 - 第一次写入需带
writeConcern: {w: "majority"},否则无法生成可追踪的逻辑时间戳 - 后续读取必须指定
readConcern: "majority",且不能跨 session 复用 - Node.js 驱动中,需显式调用
session.startTransaction()才启用事务语义,但因果一致性不依赖startTransaction()
因果一致性解决的是“我刚写的,下次读一定能看见”这类场景
典型适用场景:用户注册(写入用户文档)→ 立即跳转个人页(读取该用户)。此时不用事务,而用因果一致性会话即可避免读不到自己刚写的数据。但如果要保证“扣款+更新余额+记录流水”三者全成功或全失败,就必须用事务,而非仅靠因果一致性。
因果一致性的代价是轻微延迟:MongoDB 需等待 majority 节点确认写入后才允许后续读取,对低延迟敏感的读操作(如首页缓存穿透查询)反而不适合启用。
驱动层启用因果一致性的最小必要配置
以 Node.js 驱动为例,关键不是连接字符串加参数,而是每次会话初始化时明确声明:
const session = client.startSession({ causalConsistency: true });
// 后续所有操作都必须复用这个 session 对象
await collection.insertOne({ name: "alice" }, { session });
await collection.findOne({ name: "alice" }, { session, readConcern: { level: "majority" } });
注意:causalConsistency: true 必须在 startSession() 时传入,之后无法动态开启;readConcern 必须每次读操作单独指定,不会继承 session 默认值;副本集必须启用 majority writeConcern 支持,否则会直接报错 Majority write concern is not enabled。
因果一致性的真正难点不在代码怎么写,而在理解它不保证全局顺序、不替代事务、也不缓解网络分区下的读写冲突——它只锚定单一会话内操作的逻辑先后关系。一旦混用多个 session 或跨服务传递 session ID,因果链就断了。


















