MongoDB 4.0单机模式不支持事务,必须升级为单成员副本集并配置readConcern="snapshot"和writeConcern={w:"majority"};需用--replSet启动、rs.initiate()初始化,且连接字符串须含?replicaSet=rs0。

直接改不行,MongoDB 4.0 单机实例默认不启用副本集功能,事务(session.startTransaction())必须在副本集或分片集群中才能使用。你需要先初始化副本集,再确保写关注和读关注配置正确,否则事务会报 Transaction numbers are only allowed on replica sets 或 no primary available。
停机前必须做的三件事
副本集初始化不是热操作,需要短暂停机(通常几十秒),且不能跳过校验:
- 确认当前
mongod进程使用的是--replSet启动参数(哪怕只是占位),否则rs.initiate()会失败并提示replSet not configured with --replSet - 检查数据目录权限和磁盘空间:副本集启动后会自动生成
local数据库(含oplog.rs),至少预留 1GB 空间 - 备份
mongod.conf和/data/db(或你实际的数据路径),因为rs.initiate()成功后,单机实例将永久进入副本集模式,无法退回“纯单机”状态
rs.initiate() 的最小合法配置
不要用空对象 rs.initiate({}) —— MongoDB 4.0 默认会创建一个单成员副本集,但该成员默认是 priority: 1、votes: 1,看起来能用,实则隐藏两个问题:选举超时不可控、无法添加第二节点(因 _id 冲突)。推荐显式指定配置:
rs.initiate({
_id: "rs0",
members: [{
_id: 0,
host: "localhost:27017",
priority: 2
}]
})
关键点:
-
_id必须与启动参数--replSet rs0中的值一致,大小写敏感 -
host值必须能被其他节点(未来要加的)和客户端 DNS 解析;若只本机测试,用localhost可行;生产环境务必用可解析的主机名或 IP -
priority: 2是为后续扩容留余地,避免默认值 1 导致多节点时选主逻辑复杂化
事务可用前的最后两步验证
初始化成功后,rs.status() 应显示 "stateStr" : "PRIMARY",但这还不够。事务要求:
- 连接字符串必须包含
?replicaSet=rs0(驱动自动发现主节点),否则即使连上了,startSession()也会因无法确认副本集身份而失败 - 首次事务前,执行一次带写关注的写入:
db.test.insertOne({x:1}, {writeConcern: {w:"majority"}});如果返回WriteConcernError,说明 oplog 太小或未生效,需调大storage.oplogSizeMB并重启 - 驱动层必须显式启用事务支持:Node.js 驱动需用
useUnifiedTopology: true,Python PyMongo 要确认版本 ≥ 3.9(4.0+ 更稳)
最容易被忽略的是:副本集初始化后,所有客户端连接必须重连,旧连接维持在“单机模式”下,不会自动升级为副本集上下文 —— 这会导致事务 API 静默降级为普通写入,且不报错。


















