1.用户管理
db.createUser(
{
user: "",
pwd: "",
roles: [ { role: "root", db: "admin" } ]
}
)
mongo --port 27017 -u'' -p'' --authenticationDatabase 'admin' --eval "use admin;db.createUser({user:\"r\",pwd:\"\",roles:[{role:\"clusterMonitor\",db:\"admin\"},{role:\"read\",db:\"local\"}]})"
db.updateUser("admin",{roles:[ {role:"root",db:"admin"} ]})
db.grantRolesToUser(
"mongodb_exporter",
[
{ role: "clusterMonitor", db: "admin" },{ role: "read", db: "local" },{ role: "read", db: "game" },{ role: "read", db: "common" }
]
)
#创建自定义角色
```sql
```javascript
#语法:
dbcreateRole(
{
role:"<name>",
privileges:[
{resource:{<resource>},actions:["action",]}
],
roles:[
{role:"<role>",db:"<database>"}|"<role>"
],
authenticationRestrictions:[
{clientSource:["<IP 地址>"|"<CIDR range>",],
{serverAddress:["<IP 地址>"|"<CIDR range>",]}
]
}
)
其中,resource为指定数据库或者集合,若设置为空,则默认当前数据库的全部集合。
actions:指定权限
use admin
dbcreateRole(
{
role:"role_yeyz",
privileges:[
{resource:{db:"yeyz",collection:"test"},
actions:["find","insert","update"]
}
],
roles:[
{role:"read",db:"yeyz1"}
]
}
)
dbcreateUser(
{
user: "yeyz_1",
pwd: "123456",
roles: [ { role: "role_yeyz", db: "admin" }]
}
)
2.集群管理&监控
#设置占有内存大小
db.adminCommand({setParameter: 1, wiredTigerEngineRuntimeConfig: "cache_size=52G"})
#刷脏比例调整
db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "eviction_dirty_target=1,eviction_dirty_trigger=40"})
db.adminCommand({setParameter: 1, wiredTigerEngineRuntimeConfig: "eviction=(threads_min=2,threads_max=8)"})
#初始化副本集
cfg={_id :"gz",configsvr: true,members:[{ _id: 0, host: "" },{ _id: 1, host: "" },{ _id: 2, host: "" }]}
rsconf = {
_id: "gamemongo",
members: [
{
_id: 0,
host: ":27017",
"priority":3
},
{
_id: 1,
host: ":27017",
"priority":1
},
{
_id: 2,
host: ":27017",
"priority":1
}
]
}
rs.initiate(cfg)
#调整优先级
cfg = rs.conf()
cfg.members[0].priority = 3
rs.reconfig(cfg)
#成员增减
rs.add('127.0.0.1:20001');
rs.remove()
#日志轮转
use admin
db.runCommand({ logRotate :1 } )
#慢查询阈值
db.setProfilingLevel(1,{slowms:800})
#查看执行时间较长的操作
db.currentOp({"active" : true,"secs_running" : { "$gt" : 2000 }});
#关闭节点
db.shutdownServer({timeoutSecs: 60});
#查看连接数
db.serverStatus().connections;
#查看执行操作时间较长的动作
db.currentOp({"active" : true,"secs_running" : { "$gt" : 2000 }});
3.数据操作
#索引操作
db.gameUser.createIndex({"expiretime" : 1},{ background: true, expireAfterSeconds: 86400, name: "gameUser_expiretimeIndex"})
db.gameUser.dropIndex("gameIdAndUserIdIndex")
db.gameUser.createIndex({"gameId" : 1,"userId" : 1 },{unique:true, background: true, name: "gameIdAndUserIdIndex"})
#查看最新的数据记录
db.game.find().sort({"created": -1}).limit(1)
#查看oplog最新数据
db.oplog.rs.find().sort({"created": -1}).pretty().limit(1)
#时间范围查询
db.game.find({"$and":[{"created":{"$gt":ISODate("2021-07-20T14:23:00")}},{"created":{"$lt":ISODate("2021-07-20T14:30:00")}}]}).sort({"created": -1})
#导出索引
// 当前脚本名为exportImportIndexes.js
let joinStr = "*_*";
// 查询所有表的索引
function findAllIndexes() {
// 获取所有表
let allCollections = db.getCollectionNames();
for (var colName of allCollections) {
let indexes = db.getCollection(colName).getIndexes();
// 输出表索引信息
print(colName, joinStr, JSON.stringify(indexes));
}
}
findAllIndexes();
mongo -u'' -p'' --authenticationDatabase 'admin' localhost:port/dbname index_find.js >index.log
var collectionList = db.getCollectionNames();
for (var index in collectionList) {
var collection = collectionList[index];
var cur = db.getCollection(collection).getIndexes();
if (cur.length == 1) {
continue;
}
for (var index1 in cur) {
var next = cur[index1];
if (next["key"]["_id"] == '1') {
continue;
}
print(" db.getCollection(\"" + collection + "\").ensureIndex(" + JSON.stringify(next.key) + ",{background:1, unique:" + (next.unique || false) + "" + (next.expireAfterSeconds > 0 ? ", expireAfterSeconds :" + next.expireAfterSeconds: "") + " })"
)
}
};
#mongo导出数据
./mongodump -u -p'' -h127.0.0.1:port --authenticationDatabase admin -o /data/dump
--excludeCollection 不导出某个库
对数据排序后导出csv文件
mongoexport -h 127.0.0.1:27017 -d NBSPRC -c town --sort {'code':1} --type=csv -f code,name,link -o town.csv
- -h 数据地址:端口
- -c 数据库集合名称(表名称)
- –sort 对查询结果按照某个字段进行排序
- –type=csv 指定查询结果输出格式,csv或者json
- -f 指定查询结果要输出的字段
- -o 输出文件名称
#导入数据
./mongorestore --port -u -p'' --authenticationDatabase admin -d test /data/dump/
4.Mirrored Reads
主库复制一定比例的读流量到从库,一定程度避免主从切换后 新主上大量的cache miss
db.adminCommand( { setParameter: 1, mirrorReads: { samplingRate: 0.10 } } )
5.内存占用&释放
5.1 连接和请求占⽤的内存
如果实例的连接数很⼤,可能会消耗⼀部分的内存,原因如下:
每个连接,后端都有对应处理这个连接上的请求的线程。每个线程最多可以开销1MB的线程栈,通常情况下在几十KB~几百KB。
每个TCP连接在内核层⾯有读缓冲区和写缓冲区,由TCP内核参数tcp_rmem和tcp_wmem等确定,这块的内存使⽤⽤户⽆需关⼼。但并发连接越多,默认套接字缓存越⼤,则TCP占⽤内存越⼤。
每接收到⼀个请求,会有个请求上下⽂,整个过程中可能分配很多临时缓冲区,⽐如请求包、应答包和排序的临时缓冲区等,这些在请求结束时都会释放,但这个释放只是归还给内存分配器 tcmalloc,tcmalloc优先会还到⾃⼰的cache⾥,然后逐步再归还给操作系统。
很多情况下,内存使⽤率⾼的原因是tcmalloc未及时归还内存⾄操作系统,这⼀块最⼤可能达到几十GB。
db.serverStatus().tcmalloc
tcmalloc cache = pageheap_free_bytes + total_free_bytes
5.2 创建索引过程中的内存消耗
正常的业务数据写⼊情况下,Secondary节点会维持⼀个最⼤约256M的buffer⽤于数据回放。在创建索引方面,当Primary节点创建索引完成后,Secondary节点回放过程中可能消耗更多的内存。
Secondary节点并行回放创建索引,那就会消耗更多的内存,多个索引同时创建时可能导致实例内存溢出。
5.3 引擎内存
db.serverStatus().wiredTiger.cache
bytes currently in the cache后的值为内存大小
6.cpu占用过高
6.1扫描⾏数过多
MongoDB为多线程应⽤,如果存在单个查询扫描⾏数过多,该查询所在线程的CPU占⽤时间会变⻓
1 全表扫描
当在 system.profile集合或者运⾏⽇志⽂件发现COLLSCAN关键字时,就表示该查询进行了全表扫描。通过添加索引的方法优化,如果当前已不能使用该方法,则在业务侧控制该表的数据量和执行频率。
2.索引设计和优化
除了全表扫描以外,当查询的扫描行数关键字docsExamined超过1000且执行频率较高时,我们需要关注该查询。除了全表扫描以外,造成docsExamined过多⼀般有以下情况:
- 多条件过滤时,未使⽤组合索引或不满⾜最左前缀匹配原则。
- 未使⽤索引做排序操作。
- 查询过于复杂,或者存在⼤量的聚合类操作,基本⽆法从索引层⾯做到极致优化,或者导致查询⾛错解析计划。
- 数据列的数据选择性和运⾏频率的评估错误,未能做到最好的折中。
针对以上问题的更多信息,请参见以下官⽅⽂档:
- 组合索引的原理和使⽤⽅法,详情请参见:https://docs.mongodb.com/manual/core/index-compound/。
- 使⽤索引排序,详情请参见:https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/。
- 使⽤Hint固化执⾏计划,详情请参考:https://docs.mongodb.com/manual/reference/operator/meta/hint/和https://docs.mongodb.com/manual/reference/method/cursor.hint/。
- 索引的数据选择性和运⾏频率折中⽅法,详情请参见:https://docs.mongodb.com/manual/tutorial/create-queries-that-ensure-selectivity/。
6.2并发过大
如果确认查询层⾯没有问题,那么引起实例CPU占用高的可能原因为业务并发过⾼。如果是由于业务请求量过⼤,并发过⾼导致了CPU占用高的问题
- 单实例垂直配置升降级,使得单实例能够承载更多的读写量。
- 配置副本集层⾯的读写分离,或者添加该副本的只读实例。
- 升级⾄MongoDB分⽚集群,通过数据⽔平拆分的⽅式横向,线性扩展系统性能。
- 如果是Mongos路由节点CPU占满,则直接添加Mongos节点个数并设置Mongos节点的负载均衡。
7.io过高
- 内存不够。I/O问题与内存的CacheSize⼤⼩息息相关。CacheSize越⼤,表示能够缓存的热数据越⼤
- 与磁盘I/O相关的参数和配置问题。例如MongoDB Journal和运⾏⽇志频繁刷新,写入安全机制(WriteConcern)设置不合理,分⽚集群的MoveChunk错误等。