avatar

Mongo命令与副本集

Mongo进阶

第1章 Mongo基本操作

1.1 介绍

CRUD 操作是create(创建), read(读取), update(更新)和delete(删除) 文档。
MongoDB 不支持SQL 但是支持自己的丰富的查询语言。
在MongoDB 中,存储在集合中的每个文档都需要一个唯一的_id 字段,作为主键。如果插入的文档省略了该_id字段,则MongoDB 驱动程序将自动为该字段生成一个ObjectId_id。也用于通过更新操作插入的文档upsert: true.
如果文档包含一个_id 字段,该_id 值在集合中必须是唯一的,以避免重复键错误。
在MongoDB 中,插入操作针对单个集合。MongoDB 中的所有写操作都是在单个文档的级别上进行的

1.2 显示命令

1
2
3
4
5
6
7
8
9
10
11
Help: 显示帮助。
db.help() 显示数据库方法的帮助。
db.<collection>.help() 显示收集方法的帮助, <collection>可以是现有的集合或不存在的集合的名称。
show dbs 打印服务器上所有数据库的列表。
use <db> 将当前数据库切换到<db>。该mongoshell 变量db 被设置为当前数据库。
show collections 打印当前数据库的所有集合的列表
show users 打印当前数据库的用户列表。
show roles 打印用于当前数据库的用户定义和内置的所有角色的列表。
show profile 打印需要1 毫秒或更多的五个最近的操作。有关详细信息,请参阅数据库分析器上的文档。
show databases 打印所有可用数据库的列表。
load() 执行一个JavaScript 文件。

1.3 MongoDB CRUD操作

官方文档 https://docs.mongodb.com/manual/crud/

1.插入文件

1
2
3
db.inventory.insertOne()
db.inventory.insertMany()
db.inventory.find( {} ) ---> 查询

单行插入

1
2
3
db.inventory.insertOne(
{ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)

多行插入

1
2
3
4
5
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
{ item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
{ item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])

2.查询数据

查询所有

1
2
db.inventory.find( {} )
SELECT * FROM inventory --> MySQL查询

指定条件查询

1
2
db.inventory.find( { status: "D" } )
SELECT * FROM inventory WHERE status = "D" --> MySQL查询

指定条件下使用查询运算符

从inventory 集合中检索status等于”A”或的所有文档”D”

1
2
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
SELECT * FROM inventory WHERE status in ("A", "D") --> MySQL查询

指定AND条件

检索inventory 集合中status等于”A” 和 qty数量$lt小于30的所有文档

1
2
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
SELECT * FROM inventory WHERE status = "A" AND qty < 30

指定OR条件

检索inventory 集合中status等于”A” 或 qty数量$lt小于30的所有文档

1
2
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
SELECT * FROM inventory WHERE status = "A" OR qty < 30 --> MySQL查询

指定AND和OR条件

1
2
3
4
5
6
db.inventory.find( {
status: "A",
$or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} )

SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")

查看数据库命令

1
2
3
4
5
6
7
8
9
10
11
12
> show dbs
admin 0.000GB
local 0.000GB
test 0.000GB
test2 0.000GB
> use test
switched to db test
> db
test
> show collections
inventory
test

3.更新数据

以下集合为例

1
2
3
4
5
6
7
8
9
10
11
12
db.inventory.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }
] );

更新单个文件

1
2
3
4
5
6
7
db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
}
)

更新多个文件

1
2
3
4
5
6
7
db.inventory.updateMany(
{ "qty": { $lt: 50 } },
{
$set: { "size.uom": "in", status: "P" },
$currentDate: { lastModified: true }
}
)

更换文件

下面的示例替换集合中的第一个文档, inventory其中:item: "paper"

1
2
3
4
db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)

4.删除文件

以下集合为例

1
2
3
4
5
6
7
db.inventory.insertMany( [
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
] );

删除所有文件

1
db.inventory.deleteMany({})

删除所有符合条件的文档

1
db.inventory.deleteMany({ status : "A" })

仅删除一个符合条件的文档

1
db.inventory.deleteOne( { status: "D" } )

1.4 创建索引

默认情况下,创建索引将阻止数据库上的所有其他操作。在集合上构建索引时,保存集合的数据库对于读取或写入操作是不可用的,直到索引构建完成。任何需要对所有数据库(例如listDatabases)进行读或写锁定的操作将等待前台索引构建完成。
对于可能需要长时间运行的索引创建操作,可以考虑background 选项,这样MongoDB 数据库在索引创建期间仍然是可用的。例如,在people 集合的zipcode 键上创建一个索引,这个过程在后台运行,可以使用如下方式:
db.people.createIndex( { zipcode: 1}, {background: true} )
默认MongoDB 索引创建的background 是false 。
索引优化: db.test.find({“id”:100}).explain()

1.查看执行计划

1
db.test.find({"age":{ $lt: 30 }}).explain()

2.创建索引

1
db.test.createIndex( { age: 1 } )

3.查看索引

1
db.test.getIndexes()

4.再次查看执行计划

1
2
3
关键词
"stage" : "IXSCAN"
"indexName" : "age_1"

第2章 工具介绍

官网地址

1
https://docs.mongodb.com/manual/reference/program/

MongoDB软件包中的核心组件是:mongod核心数据库进程;mongos分片集群的控制器和查询路由器; 以及 mongo交互式MongoDB Shell。

2.1 mongod

1
2
Mongod 是Mongodb 系统的主要守护进程,它处理数据请求,管理数据访问,并执行后台
管理操作。启动进程指定配置文件,控制数据库的行为

2.2 mongos

1
2
3
mongos 对于“ MongoDB Shard”,是用于处理来自应用层的查询的MongoDB 分片配置的路由服务,并确
定此数据在分片集群中的位置, 以完成这些操作。从应用程序的角度来看,一个mongos 实例与任何其他
MongoDB 实例的行为相同

2.3 Mongostat

1
Mongostat 实用程序可以快速概览当前正在运行的mongod 或mongos 实例的状态。mongostat 在功能上类似于UNIX / Linux 文件系统实用程序vmstat,但提供有关的数据mongod 和mongos 实例

2.4 Mongotop

1
2
Mongotop 提供了一种跟踪MongoDB 实例读取和写入数据的时间量的方法。mongotop 提供每个收集级别
的统计信息。默认情况下,mongotop 每秒返回一次值

2.5 Mongooplog

1
2
Mongooplog 是一个简单的工具,可以从远程服务器的复制oplog 轮询操作,并将其应用于本地服务器。此功能支持某些类型的实时迁移,这些迁移要求源服务器保持联机并在整个迁移过程中运行。通常,此命令将采用以下形式:
mongooplog - from mongodb0.example.net --host mongodb1.example.net

第3章 授权认证

3.1 官方网址

1
2
https://docs.mongodb.com/manual/reference/configuration-options/#security-options
https://docs.mongodb.com/manual/tutorial/enable-authentication/

3.2 授权介绍

1
2
3
4
5
用户管理界面
要添加用户, MongoDB 提供了该db.createUser()方法。添加用户时,您可以为用户分配色以授予权限。
注意:
在数据库中创建的第一个用户应该是具有管理其他用户的权限的用户管理员。
您还可以更新现有用户,例如更改密码并授予或撤销角色。

操作命令

1
2
3
4
5
6
7
8
9
10
11
db.auth() 将用户验证到数据库。
db.changeUserPassword() 更改现有用户的密码。
db.createUser() 创建一个新用户。
db.dropUser() 删除单个用户。
db.dropAllUsers() 删除与数据库关联的所有用户。
db.getUser() 返回有关指定用户的信息。
db.getUsers() 返回有关与数据库关联的所有用户的信息。
db.grantRolesToUser() 授予用户角色及其特权。
db.removeUser() 已过时。从数据库中删除用户。
db.revokeRolesFromUser() 从用户中删除角色。
db.updateUser() 更新用户数据。

3.3 创建用户和角色

1.创建管理用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mongo db01:27017
use admin
db.createUser(
{
user: "admin",
pwd: "123456",
roles:[
{
role: "root",
db:"admin"
}
]
}
)

2.查看创建的用户

1
db.getUsers()

3.配置文件添加权限认证参数

1
2
3
4
security: #认证
authorization: enabled
#启用或者禁用基于角色的访问控制来管理每个用户对数据库资源和操作的访问
enabled 或者 disables

4.重启mongo

1
2
mongod -f /opt/mongo_27017/conf/mongodb.conf --shutdown
mongod -f /opt/mongo_27017/conf/mongodb.conf

5.登录

配置问权限认证后需要重启节点,再次登陆如果不使用账号密码就查看不了数据

1
mongo db01:27017 -uadmin -p --authenticationDatabase admin

6.创建其他用户

1
2
3
4
5
6
7
8
9
use test
db.createUser(
{
user: "mysun",
pwd: "123456",
roles: [ { role: "readWrite", db: "write" },
{ role: "read", db: "read" } ]
}
)

7.创建测试数据

1
2
3
4
5
6
7
8
9
10
11
12
13
use write
db.write.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.write.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.write.insert({"name":"yazhang","age":28,"ad":"北京市朝阳区"})
db.write.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区"})
db.write.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区","sex":"boy"})

use read
db.read.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.read.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.read.insert({"name":"yazhang","age":28,"ad":"北京市朝阳区"})
db.read.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区"})
db.read.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区","sex":"boy"})

8.退出admin,使用mysun用户登录

1
2
3
4
5
6
7
8
mongo db01:27017 -umysun -p --authenticationDatabase test
use write
db.write.find()
db.write.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})

use read
db.read.find()
db.read.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})

第4章 副本集配置

4.1 官方网站

1
https://docs.mongodb.com/manual/replication/

在MongoDB中复制
副本集是一组mongod维护相同数据集的实例。一个副本集包含多个数据承载节点和一个仲裁器节点(可选)。在数据承载节点中,只有一个成员被视为主要节点,而其他节点则被视为次要节点。

所述主节点接收所有的写操作。副本集只能有一个能够确认与 写入有关的写入的主数据库。尽管在某些情况下,另一个mongod实例可能会暂时认为自己也是主要实例。 [1]主数据库在其操作日志(即oplog)中记录对其数据集的所有更改

该次级复制初级的OPLOG和应用操作的数据集,使得次级数据集反映了主要的数据集。如果主要节点不可用,则符合条件的次要节点将进行选举以自行选举新的主要节点。

您可以将一个额外的mongod实例作为仲裁器添加到副本集 。仲裁者不维护数据集。仲裁程序的目的是通过响应其他副本集成员的心跳和选举请求来维护副本集中的仲裁。由于仲裁器不存储数据集,因此它是提供副本集仲裁功能且资源成本比具有数据集的功能齐全的副本集成员便宜的好方法。如果您的副本集成员数为偶数,请添加仲裁程序以majority在主要选举中获得票数。仲裁器不需要专用硬件。

异步复制

辅助节点复制主节点的操作日志,并将操作异步应用于其数据集。通过使次要节点的数据集反映主要节点的数据集,即使一个或多个成员失败,副本集也可以继续运行。

复制延迟和流控制

复制滞后是指将操作上的写操作复制(即复制)到辅助上所花费的时间 。可以接受一些小的延迟时间,但是随着复制滞后的增加会出现严重的问题,包括在主数据库上增加缓存压力。

从MongoDB 4.2开始,管理员可以限制主数据库应用其写入的速率,以将延迟保持在可配置的最大值以下。majority committedflowControlTargetLagSeconds

默认情况下,流量控制为enabled

1
2
#注意
为了启用流控制,副本集/分片集群必须具有:featureCompatibilityVersion(FCV) of 4.2并读取关注。也就是说,如果未启用FCV 或禁用了多数读功能,则启用的流控制无效。majority enabled4.2

自动故障转移

当主节点与集合中的其他成员的通信electionTimeoutMillis时间超过配置的时间段(默认为10秒)时,合格的辅助节点将要求选举以提名自己为新的主节点。群集尝试完成新主数据库的选择并恢复正常操作。

4.2 创建多实例副本集

1.创建节点目录和数据目录

1
2
mkdir -p /opt/mongo_2801{7,8,9}/{conf,logs,pid}
mkdir /data/mongo_2801{7,8,9} -p

2.创建配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
cat >/opt/mongo_28017/conf/mongo_28017.conf <<EOF
systemLog:
destination: file
logAppend: true
path: /opt/mongo_28017/logs/mongodb.log

storage:
journal:
enabled: true
dbPath: /data/mongo_28017
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true

processManagement:
fork: true
pidFilePath: /opt/mongo_28017/pid/mongod.pid

net:
port: 28017
bindIp: 127.0.0.1,10.0.1.51

replication:
oplogSizeMB: 1024
replSetName: dba
EOF

3.复制配置文件到其他节点

1
2
cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28018/conf/mongo_28018.conf
cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28019/conf/mongo_28019.conf

4.替换端口号

1
2
sed -i 's#28017#28018#g' /opt/mongo_28018/conf/mongo_28018.conf  
sed -i 's#28017#28019#g' /opt/mongo_28019/conf/mongo_28019.conf

5.启动所有节点

1
2
3
4
mongod -f /opt/mongo_27017/conf/mongodb.conf --shutdown
mongod -f /opt/mongo_28017/conf/mongo_28017.conf
mongod -f /opt/mongo_28018/conf/mongo_28018.conf
mongod -f /opt/mongo_28019/conf/mongo_28019.conf

6.初始化集群

1
2
3
4
5
6
7
8
9
10
11
12
13
mongo db01:28017
config = {
_id : "dba",
members : [
{_id : 0, host : "db01:28017"},
{_id : 1, host : "db01:28018"},
{_id : 2, host : "db01:28019"},
]
}

rs.initiate(config)

rs.status() ---> 查看状态

7.插入数据

1
2
3
4
5
6
7
db.inventory.insertMany( [
{ "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
{ "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
{ "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
{ "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
{ "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]);

8.副本节点登录查看数据

1
2
3
4
5
mongo db01:28018
rs.slaveOk();
show dbs
use test
db.inventory.find()

9.设置副本可读

1
echo "rs.slaveOk();" > /root/.mongorc.js

4.3 副本集权重调整

1.查看当前副本集配置

1
rs.conf()

2.设置权重

1
2
3
config=rs.conf()
config.members[0].priority=100
rs.reconfig(config)

3.主节点主动降级

1
rs.stepDown()

4.4 增加新节点和删除旧节点

1.创建新节点并启动

1
2
3
4
5
6
mkdir /opt/mongo_28010/{conf,logs,pid} -p
mkdir /data/mongo_28010
cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28010/conf/mongo_28010.conf
sed -i 's#28017#28010#g' /opt/mongo_28010/conf/mongo_28010.conf
mongod -f /opt/mongo_28010/conf/mongo_28010.conf
mongo db01:28010

2.集群添加节点

1
rs.add("db01:28010")

3.删除节点

1
rs.remove("db01:28010")

4.5 仲裁节点

1.创建新节点并启动

1
2
3
4
5
6
mkdir /opt/mongo_28011/{conf,logs,pid} -p
mkdir /data/mongo_28011
cp /opt/mongo_28017/conf/mongo_28017.conf /opt/mongo_28011/conf/mongo_28011.conf
sed -i 's#28017#28011#g' /opt/mongo_28011/conf/mongo_28011.conf
mongod -f /opt/mongo_28011/conf/mongo_28011.conf
mongo db01:28011

2.将仲裁节点加入集群

1
2
mongo db01:28018
rs.addArb("db01:28011")

第5章 mongo备份与恢复

1.工具介绍

1
2
3
4
5
6
7
#(1)mongoexport/mongoimport
mongoimport提供了一种获取JSON, CSV或TSV中的数据并将其导入mongod 实例的方法。mongoexport提供了一种将数据从mongod实例导出到JSON,CSV或TSV的方法。

#注意
BSON与其他格式之间的转换缺乏完整的类型保真度。因此,您不能将mongoimport和 mongoexport用于往返导入和导出操作。
#(2)mongodump/mongorestore
mongodump提供了一种 从实例创建BSON转储文件的方法mongod,同时 mongorestore还可以还原这些转储。bsondump将BSON转储文件转换为 JSON

2.应用场景

1
2
3
4
5
6
1.异构平台迁移  mysql <---> mongodb
2.同平台,跨大版本:mongodb 2 ----> mongodb 3
mongoexport/mongoimport:json csv

日常备份恢复时使用
mongodump/mongorestore

3.导出工具mongoexport

单表备份

1
mongoexport --port 27017 -d test -c inventory -o /data/inventory.json

单表备份至csv格式

1
2
mongoexport --port 27017 -d test -c test --type=csv -f name,age,ad -o /data/test.csv
#说明:test目标数据库,第二个test目标集合,test.csv要保存的文件,--type指定导出的格式,默认是json,-f后面是需要导出的字段名称,多个字段名用逗号隔开

4.恢复

1
2
3
4
mongoimport --port 27017 -d test -c inventory /data/inventory.json

mongoimport --port 27017 -d test -c test --type=csv --headerline --file /data/test.csv
# 说明:test目标数据库,第二个test目标集合,test.csv要导入的文件,--type指定导出的格式,默认是json,--headerline批明不导入第一行

5.mysql数据迁移到mongo

1
2
select * from world.city into outfile '/data/city2.csv' fields terminated by ',';
mongoimport --port 27017 -d world -c city --type=csv --headerline --file /data/city2.csv

6.导出与恢复

1
2
mongodump  --port 27017 -o /data/backup
mongorestore --port 27017 -d world /data/backup/world/ --drop

7.模拟误删除恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
oplog

db.oplog.rs.find().pretty()
{
"ts" : Timestamp(1572983861, 1),
"t" : NumberLong(13),
"h" : NumberLong("4118963721380445998"),
"v" : 2,
"op" : "c",
"ns" : "wo.$cmd",
"ui" : UUID("cb1848ae-8b34-4c76-b832-158324376723"),
"wall" : ISODate("2019-11-05T19:57:41.679Z"),
"o" : {
"drop" : "ci"
}
}

mongorestore --port 28017 --oplogReplay --oplogLimit "1572983861:1" --drop /data/backup/

8.Mongodump备份数据

1
2
3
4
5
6
mongodump -h dbhost -d dbname -o dbdirectory

#说明
-h:MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-d:需要备份的数据库实例,例如:test
-o:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。

9.Mongorestore恢复数据

1
2
3
4
5
6
mongorestore -h dbhost -d dbname -directoryperdb dbdirectory

#说明
-h:MongoDB所在服务器地址
-d:需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
-directoryperdb:备份数据所在位置,例如:c:\data\dump\test
文章作者: Wu Fei
文章链接: http://linuxwf.com/2020/04/15/Mongo%E5%91%BD%E4%BB%A4%E4%B8%8E%E5%89%AF%E6%9C%AC%E9%9B%86/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 WF's Blog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论