readConcern: "majority"在分片集群中仅对单个shard生效,不保证跨分片一致性;需依赖multi-document transaction配合readConcern: "snapshot"和writeConcern: "majority"才能实现跨分片强一致。
你设了 readConcern: "majority",但跨分片读取时仍可能看到不一致的数据——这不是 bug,是设计如此。每个分片(shard)本身是一个独立副本集,readConcern: "majority" 只约束该 shard 内部的读视图,不协调其他 shard 的状态。
常见错误现象:
find().readConcern({level: "majority"}),t1 从 shard A 读到新值,t2 从 shard B 读到旧值mongosh 直连某个 shard 的 mongod,手动设 readConcern,结果报错 ReadConcernMajorityNotAvailableYet
原因通常是:
votes: 0),无法形成 majority 投票writeConcern: {w: 1},导致 majority 视图始终滞后于实际写入storage.journal.enabled: false),snapshot 机制无法稳定提供 majority 级别快照只有开启事务,且所有操作落在同一分片(或通过 allowDiskUse: true 支持跨分片事务),MongoDB 才会启用分布式事务协调器(由 mongos 驱动),统一应用 readConcern 和 writeConcern 约束。
实操要点:
session.startTransaction(),不能靠自动 commitwriteConcern: {w: "majority"} 和 readConcern: "snapshot" 同时生效snapshot 级别回滚语义示例中漏掉 session 参数,或在事务外调用 updateOne,都会让事务降级为普通写入。
readConcern: "majority" 不是独立开关,它依赖写操作已获得多数确认。如果写入只等主节点(w: 1),那所谓“多数视图”永远等于主节点当前状态,毫无意义。
关键参数组合:
priority: 0, votes: 0 的仲裁节点updateOne(..., {writeConcern: {w: "majority"}}),不能依赖连接串默认值mongos 默认转发 writeConcern 到目标 shard,但若 shard 副本集配置异常(如 secondary 落后超 10 秒),w: "majority" 可能超时失败readConcern 解决的是并发读写可见性问题,不是宕机数据丢失。持久性保障靠两件事:journal 日志刷盘、定期 fsync。
Ubuntu 上验证 journal 是否启用:
mongod --version# 然后检查 systemd service 文件里是否含 --journal 或 storage.journal.enabled: true
容易被忽略的点:
noatime,barrier=0 等激进优化,WAL 日志仍可能丢失storage.syncPeriodSecs: 60(默认值)意味着最多 60 秒未刷盘数据可能丢失,生产环境建议调为 0 或 1db.runCommand({validate: "coll"}))只能查结构损坏,无法发现因网络分区导致的逻辑不一致(比如某 shard 漏同步了一段 oplog)真正要验证分片间数据一致,得用 dbHash 对比各 shard 的校验和,或者用 sh.status() 查看 chunk 分布与迁移历史是否干净。