MongoDB 本身没有全局“只读模式”开关,所谓“只读”必须靠权限控制(用户角色)实现;setParameter: readOnly: true 是无效配置,该参数在官方文档中不存在,任何尝试在 mongod.conf 中设置它都不会生效。

直接说结论:MongoDB 本身没有全局“只读模式”开关,所谓“只读”必须靠权限控制(用户角色)实现;setParameter: readOnly: true 是无效配置,该参数在 MongoDB 官方文档中不存在,任何尝试在 mongod.conf 中设置它都不会生效。
创建只读用户时,role 和 db 参数必须匹配实际访问目标
只读权限不是靠数据库开关控制的,而是绑定到具体用户+具体数据库的。常见错误是:用户创建在 admin 库,但 roles 中指定 db: "myapp",结果连接时没显式指定认证库,导致权限不生效。
- 必须用
use admin切换到认证库后再执行db.createUser() -
roles数组里每个对象的db字段,必须是你想限制只读的那个业务数据库名(如"orders"),不能写错或留空 - 如果用户需要跨多个库只读,得分别授予多个
{role: "read", db: "xxx"},而不是用readAnyDatabase—— 后者权限过大,违反最小权限原则
连接时必须显式指定 authenticationDatabase
很多客户端(如 Compass、Node.js 驱动、mongo shell)默认把连接字符串里的数据库名当作认证库,这会导致只读用户无法登录或权限失效。
- 正确连接字符串示例:
mongodb://readonly_user:pwd@localhost:27017/myapp?authSource=admin,其中authSource=admin明确告诉驱动:用户信息存在admin库 - 在 mongo shell 中,不能只做
db.auth("u", "p"),必须先use admin再db.auth(...) - Compass 中启用 “Read-only mode” 只是前端 UI 锁定操作按钮,后端仍依赖真实用户权限 —— 如果用户本身有写权限,这个开关形同虚设
测试只读是否真正生效,别只看 find()
只读权限容易被误判,因为 find() 成功不代表没写权限。真正验证要主动触发写操作并观察错误。
- 用只读用户连接后,执行
db.collection.insertOne({})或db.collection.updateOne(...),应返回not authorized on xxx to execute command - 注意:某些聚合操作(如
$out、$merge)本质是写操作,也会被拒绝 —— 这是正常行为,不是 bug - 避免用
db.getSiblingDB("otherdb").collection.find()绕过权限检查:只要用户没被授予otherdb的read角色,这条语句会直接报错
最容易被忽略的一点:副本集或分片集群中,只读用户必须在每个分片的 admin 库(或对应 config server 的 admin)上重复创建,否则在某些路由场景下权限可能不一致。自动同步角色只存在于单机或主从结构,分片环境下必须手动保障角色一致性。


















