该错误表明mongodb未启用副本集或分片集群,事务功能强制要求replica set或mongos。需配置replsetname、执行rs.initiate()、连接uri中指定replicaset参数,并确保节点状态为primary。

事务报错 “Transaction numbers are only allowed on a replica set member or mongos”
这个错误不是代码写错了,而是 MongoDB 服务本身不支持事务——它运行在单机(Standalone)模式下,而事务强制要求副本集(replica set)或 mongos 路由节点。
常见触发场景:Spring Boot 应用开启 @Transactional、Java 驱动调用 session.startTransaction()、或直接在 mongosh 里执行事务命令时出现。
- 检查当前实例是否为副本集:连接后运行
rs.status(),若提示not master或no replset config,说明未启用副本集 - 单机模式下禁用事务逻辑是最快绕过方式;但若业务强依赖事务,必须升级部署形态
- Docker 用户注意:
mongod --replSet rs0启动后仍需手动运行rs.initiate(),否则仍视为 Standalone - 配置文件中启用副本集需同时设置
replSetName和enableMajorityReadConcern: true,缺一不可
启动失败报错 “Attempted to create a lock file on a read-only directory”
这个 IllegalOperation 和事务无关,是 MongoDB 进程无法在数据目录(如 /data/db)写入锁文件导致的硬性失败,服务根本起不来。
根本原因通常是权限、挂载或 SELinux 三者之一卡住,而不是 MongoDB 配置本身有问题。
- 先确认目录可写:
ls -ld /data/db看属主是否为mongod用户,权限至少含w(如drwxr-xr-x不够,需chown mongod:mongod /data/db && chmod 755 /data/db) - 检查挂载选项:
mount | grep "$(df /data/db | tail -1 | awk '{print $1}'),输出含ro就得sudo mount -o remount,rw /data - SELinux 启用时,
ls -Z /data/db应显示mongod_var_lib_t类型,否则运行sudo chcon -Rv --type=mongod_var_lib_t /data/db - 容器环境常见于绑定挂载(bind mount)目录权限继承宿主机 root,需在
docker run中加--user mongodb:mongodb或提前chown
聚合管道中误用事务相关阶段导致 IllegalOperation
即使副本集已就绪,某些聚合操作仍会触发 IllegalOperation,典型如在 $lookup 或 $out 阶段跨数据库/跨分片写入,或在事务内使用了不支持的阶段(如 $changeStream)。
这类错误往往出现在迁移脚本或动态构造 pipeline 的场景,日志里会明确提示 “not supported in transactions” 或类似描述。
- 事务内禁止使用
$out、$merge(除非目标集合在同一分片且满足 write concern majority) -
$lookup若指向其他数据库的集合,在事务中默认被拒绝;需确保所有引用集合位于同一数据库,或显式开启allowDiskUse: true并验证副本集配置 - 避免在事务中调用
db.runCommand({ "aggregate": ... })包裹整个 pipeline —— 改用session.getDatabase(...).collection(...).aggregate(...)显式绑定会话 - 驱动版本影响行为:MongoDB Java Driver 4.11+ 对事务内聚合限制更严格,降级到 4.9 可能掩盖问题但不推荐,应修正 pipeline 逻辑
为什么 rs.initiate() 后还是报 IllegalOperation?
副本集初始化成功 ≠ 事务就绪。常见疏漏点在于:节点状态未真正变为 PRIMARY,或客户端连接串没带 ?replicaSet=rs0 参数,导致驱动认为连的是普通单机节点。
哪怕 rs.status().myState === 1,如果连接时没声明副本集名,事务 API 仍会被拒绝。
- 检查连接 URI 是否包含
replicaSet=rs0(例如mongodb://localhost:27017/test?replicaSet=rs0) - 确认
mongosh连接后执行db.runCommand({isMaster: 1})返回字段含"hosts"和"setName",而非空数组 - Spring Boot 的
spring.data.mongodb.uri必须显式带上?replicaSet=rs0,仅靠spring.data.mongodb.auto-index-creation=true无法激活事务上下文 - 初始化脚本中若用
rs.initiate({...})但未等待rs.status().members[0].stateStr === "PRIMARY"就执行事务,可能因选举未完成而失败
IllegalOperation 错误码上,但根因天差地别。











