mongo数据库详细教程

第1章 NoSQL 介绍

1.1 NoSQL 简介

NoSQL(NoSQL = Not Only SQL ),意即”不仅仅是 SQL”。
在现代的计算系统上每天网络上都会产生庞大的数据量。
这些数据有很大一部分是由关系数据库管理系统(RDMBSs)来处理。 1970 年 E.F.Codd’s 提出的
关系模型的论文 “A relational model of data for large shared data banks”,这使得数据建模和应用程
序编程更加简单。
通过应用实践证明,关系模型是非常适合于客户服务器编程,远远超出预期的利益,今天它是结构
化数据存储在网络和商务应用的主导技术。
NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至 2009 年趋势越发高涨。NoSQL
的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是
一种全新的思维的注入。

1.2 什么是 NoSQL

NoSQL,指的是非关系型的数据库。NoSQL 有时也称作 Not Only SQL 的缩写,是对不同于传统的
关系型数据库的数据库管理系统的统称。
对 NoSQL 最普遍的解释是”非关联型的”,强调 Key-Value Stores 和文档数据库的优点,而不是单
纯的反对 RDBMS。
NoSQL 用于超大规模数据的存储。(例如谷歌或 Facebook 每天为他们的用户收集万亿比特的数
据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

1.3 为什么使用 NoSQL ?

今天我们可以通过第三方平台(如:Google,Facebook 等)可以很容易的访问和抓取数据。用户的个
人信息,社交网络,地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这
些用户数据进行挖掘,那 SQL 数据库已经不适合这些应用了, NoSQL 数据库的发展也却能很好的处
理这些大的数据。

第2章 MongoDB 简介

Mongodb 由 C++语言编写的,是一个基于分布式文件存储的开源数据库系统。,是专为可扩展性,
高性能和高可用性而设计的数据库, 是非关系型数据库中功能最丰富,最像关系型数据库的,它支
持的数据结构非常散,是类似 json 的 bjson 格式,因此可以存储比较复杂的数据类型。
MongoDB 的(来自于英文单词“了 Humongous”,中文含义为“庞大”)是可以应用于各种规模
的企业,各个行业以及各类应用程序的开源数据库。作为一个适用于敏捷开发的数据库,MongoDB
的的数据模式可以随着应用程序的发展而灵活地更新。
MongoDB 以一种叫做 BSON(二进制 JSON)的存储形式将数据作为文档存储。具有相似结构的
文档通常被整理成集合。可以把这些集合看成类似于关系数据库中的表: 文档和行相似, 字段和
列相似。

2.1 MongoDB 数据格式

2.1.1 JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON 采用完全独立于语言的文本
格式,但是也使用了类似于 C 语言家族的习惯(包括 C、 C++、 C#、 Java、JavaScript、 Perl、
Python 等)。这些特性使 JSON 成为理想的数据交换语言.易于人阅读和编写,同时也易于机器解析
和生成(一般用于提升网络传输速率)。JSON 的官方 MIME 类型是 application/json,文件扩展名
是.json。
MongoDB 使用 JSON(JavaScript ObjectNotation)文档存储记录。
JSON 简单说就是 JavaScript 中的对象和数组,通过对象和数组可以表示各种复杂的结构。
对象:
对象在 js 中表示为“{}”括起来的内容,数据结构为 {key: value,key: value,…}的键值对的
结构,在面向对象的语言中, key 为对象的属性, value 为对应的属性值,所以很容易理解,取值
方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。
例如: {"FirstName":"ke","LastName":"me","email":"hikeme@aa"}
取值方式和所有语言中一样,使用 key 获取,字段值的类型可以是 数字、字符串、数组、对象几种。
2.1.2 BSON
BSON 是一种类 JSON 的一种二进制形式的存储格式,简称 Binary JSON,它和 JSON 一样,支持内
嵌的文档对象和数组对象,但是 BSON 有 JSON 没有的一些数据类型,如 Date 和 BinData 类型。
它的优点是灵活性高,但它的缺点是空间利用率不是很理想。
BSON 有三个特点:轻量性、可遍历性、高效性。
对 JSON 来说,数据存储是无类型的,比如你要修改基本一个值,从 9 到 10,由于从一个字符变成
了两个,所以可能其后面的所有内容都需要往后移一位才可以。而使用 BSON,你可以指定这个列
为数字列,那么无论数字从 9 长到 10 还是 100,我们都只是在存储数字的那一位上进行修改,不会
导致数据总长变大。当然,在 MongoDB 中,如果数字从整形增大到长整型,还是会导致数据总长
变大的。
有时 BSON 相对 JSON 来说也并没有空间上的优势,比如对{“sex”:1},在 JSON 的存储上
1 只使用了一个字节,而如果用 BSON,那就是至少 4 个字节

2.2 MongoDB 特点

高性能: Mongodb 提供高性能的数据持久性,尤其是支持嵌入式数据模型减少数据库系统上的
I/O 操作,索引支持能快的查询,并且可以包括来嵌入式文档和数组中的键
丰富的语言查询: Mongodb 支持丰富的查询语言来支持读写操作(CRUD)以及数据汇总,文本
搜索和地理空间索引
高可用性: Mongodb 的复制工具,成为副本集,提供自动故障转移和数据冗余,
水平可扩展性: Mongodb 提供了可扩展性,作为其核心功能的一部分,分片是将数据分,在一组
计算机上。
支持多种存储引擎: WiredTiger 存储引擎和、 MMAPv1 存储引擎和 InMemory 存储引擎

2.3 MongoDB 包含的程序

MongoDB Drivers 
官方 MongoDB 客户端库提供 C, C ++, C#, Java, Node.JS, Perl, PHP,Python, Ruby
和 Scala 驱动程序的参考指南。
MongoDB Stitch 
为开发人员提供了一个 API 到 MongoDB 和其他后端服务。保持 MongoDB 的全部功能和灵性,同
时受益于强大的系统来配置细粒度的数据访问控制。
MongoDB Atlas 
MongoDB 在云中部署,操作和扩展的最佳方式。适用于 AWS,Azure 和 Google Cloud Platform。轻
松将数据迁移到 MongoDB Atlas,零停机
MongoDB Cloud Manager 
是一个用于管理 MongoDB 部署的软件包。 Ops Manager 提供 Ops Manager 监控和 Ops Manager 备
份,可帮助用户优化群集并降低操作风险
MongoDB Charts 
可以最快速最简单的创建 Mongodb 可视化图表
MongoDB Connector for BI 
MongoDB 商业智能连接器(BI)允许用户使用 SQL 创建查询,并使用现有的关系商业智能工具
(如 Tableau, MicroStrategy 和 Qlik)对其 MongoDB Enterprise 数据进行可视化,图形化和报告。
MongoDB Compass 
通过从集合中随机抽样一个文档子集,为用户提供其 MongoDB 模式的图形视图。采样文件可最大
程度地降低对数据库的影响,并能快速产生结果。有关 抽样的更多信息
MongoDB Spark Connector 
使用连接器,您可以访问所有使用 MongoDB 数据集的 Spark 库:用 SQL 进行分析的数据集(受益
于自动模式推理),流式传输,机器学习和图形 API。您也可以使用连接器与 Spark Shell。

第3章 应用场景

https://www.zhihu.com/question/32071167

第4章 安装部署

4.1 官方文档

https://docs.mongodb.com/manual/?_ga=2.57024426.1834178963.1557492386-
816165234.1557492386

4.2 安装方式

官方下载地址:https://www.mongodb.com/download-center/community
这里选用 tar 包的安装方式:https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.13.tgz

4.3 目录规划

以软连接形式放在/opt 目录下

4.4 软件安装

[root@db01 ~]# yum install libcurl openssl -y
[root@db01 ~]# mkdir /opt/mongo_cluster/ -p
[root@db01 ~]# mkdir /data/soft -p
[root@db01 ~]# cd /data/soft/
[root@db01 /data/soft]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.13.tgz
[root@db01 /data/soft]# tar zxvf mongodb-linux-x86_64-3.6.13.tgz -C /opt/mongo_cluster/
[root@db01 /data/soft]# cd /opt/mongo_cluster/
[root@db01 /opt/mongo_cluster]# ln -s mongodb-linux-x86_64-3.6.13 mongodb
[root@db01 /opt/mongodb_cluster]# mkdir /opt/mongo_cluster/mongo_27017/{conf,logs,pid} -p
[root@db01 /opt/mongodb_cluster]# mkdir /data/mongo_cluster/mongo_27017 -p

4.5 配置文件

参考博客
https://blog.csdn.net/MatrixGod/article/details/82585778
配置文解释:
systemLog:
 destination: file #Mongodb 日志输出的目的地,指定一个 file 或者 syslog,如果指定 file,必须指定
 logAppend: true #当实例重启时,不创建新的日志文件,在老的日志文件末尾继续添加
 path: /opt/mongo_cluster/mongo_27017/logs/mongodb.log #日志路径
storage:
 journal: #回滚日志
 enabled: true
 dbPath: /data/mongo_cluster/mongo_27017 #数据存储目录
 directoryPerDB: true #默认 false,不适用 inmemory engine
 wiredTiger:
 engineConfig:
 cacheSizeGB: 1 #将用于所有数据缓存的最大小
 directoryForIndexes: true #默认 false 索引集合 storage.dbPath 存储在数据单独子目录
 collectionConfig:
 blockCompressor: zlib
 indexConfig:
 prefixCompression: true
processManagement: #使用处理系统守护进程的控制处理
 fork: true #后台运行
 pidFilePath: /opt/mongo_cluster/mongo_27017/pid/mongod.pid #创建 pid 文件
net:
 port: 27017 #监听端口
 bindIp: 127.0.0.1,10.0.0.51 #绑定 ip
写入配置文件
[root@db01 ~]# cat > /opt/mongo_cluster/mongo_27017/conf/mongodb.conf << EOF
systemLog:
 destination: file 
 logAppend: true 
 path: /opt/mongo_cluster/mongo_27017/logs/mongodb.log
storage:
 journal:
 enabled: true
 dbPath: /data/mongo_cluster/mongo_27017
 directoryPerDB: true
 wiredTiger:
 engineConfig:
 cacheSizeGB: 1
 directoryForIndexes: true
 collectionConfig:
 blockCompressor: zlib
 indexConfig:
 prefixCompression: true
processManagement:
 fork: true
 pidFilePath: /opt/mongo_cluster/mongo_27017/pid/mongod.pid
net:
 port: 27017
 bindIp: 127.0.0.1,10.0.0.51
EOF

4.6 启动关闭

4.6.1 启动命令
[root@db01 ~]# /opt/mongodb/bin/mongod -f /opt/mongodb/conf/mongodb.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 3024
child process started successfully, parent exiting
4.6.2 检查命令
[root@db01 ~]# ps -ef|grep mongo
root 3024 1 3 10:26 ? 00:00:00 /opt/mongodb/bin/mongod -f 
/opt/mongodb/conf/mongodb.conf
root 3049 1827 0 10:26 pts/0 00:00:00 grep -E --color=auto --color=auto mongo
[root@db01 ~]# netstat -lntup|grep 27017
tcp 0 0 10.0.0.51:27017 0.0.0.0:* LISTEN 3024/mongod 
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 3024/mongod 
[root@db01 ~]# ll /data/mongodb/
总用量 72
drwx------ 4 root root 35 7 月 6 10:26 admin
drwx------ 4 root root 35 7 月 6 10:26 config
drwx------ 2 root root 69 7 月 6 10:27 diagnostic.data
drwx------ 2 root root 107 7 月 6 10:26 journal
drwx------ 4 root root 35 7 月 6 10:26 local
-rw------- 1 root root 16384 7 月 6 10:27 _mdb_catalog.wt
-rw------- 1 root root 5 7 月 6 10:26 mongod.lock
-rw------- 1 root root 4096 7 月 6 10:26 sizeStorer.wt
-rw------- 1 root root 114 7 月 6 10:26 storage.bson
-rw------- 1 root root 45 7 月 6 10:26 WiredTiger
-rw------- 1 root root 4096 7 月 6 10:26 WiredTigerLAS.wt
-rw------- 1 root root 21 7 月 6 10:26 WiredTiger.lock
-rw------- 1 root root 1095 7 月 6 10:27 WiredTiger.turtle
-rw------- 1 root root 28672 7 月 6 10:27 WiredTiger.wt
4.6.3 写入环境变量
[root@db01 ~]# echo 'PATH=$PATH:/opt/mongodb/bin' >> /etc/profile 
[root@db01 ~]# tail -1 /etc/profile
PATH=$PATH:/opt/mongodb/bin 
[root@db01 ~]# source /etc/profile
[root@db01 ~]# mongo
mongo mongoexport mongoperf mongos 
mongod mongofiles mongoreplay mongostat 
mongodump mongoimport mongorestore mongotop
4.6.4 创建 hosts 解析
[root@db01 ~]# cat > /etc/hosts <<EOF
10.0.0.51 db01
10.0.0.52 db02
10.0.0.53 db03
EOF
4.6.5 连接命令
[[root@db01 ~]# mongo db01:27017
MongoDB shell version v3.6.13
connecting to: mongodb://db01:27017/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("5dccc8f1-3e0e-4001-9361-4b4d9b6b2a8c") }
MongoDB server version: 3.6.13
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
 http://docs.mongodb.org/
Questions? Try the support group
 http://groups.google.com/group/mongodb-user
Server has startup warnings: 
2019-07-06T10:26:37.135+0800 I STORAGE [initandlisten] 
2019-07-06T10:26:37.135+0800 I STORAGE [initandlisten] ** WARNING: The configured WiredTiger 
cache size is more than 80% of available RAM.
2019-07-06T10:26:37.135+0800 I STORAGE [initandlisten] ** See 
http://dochub.mongodb.org/core/faq-memory-diagnostics-wt
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] 
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled 
for the database.
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** Read and write access to data 
and configuration is unrestricted.
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** WARNING: You are running this process 
as the root user, which is not recommended.
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] 
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] 
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** WARNING: 
/sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten]
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** WARNING: 
/sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] 
>
4.6.6 关闭命令
2 种关闭方式,建议使用 mongo 自带的命令
方法 1:登陆 mongo 使用内置 shutdown 命令
使用这条命令的前提是必须使用 localhost 登陆,否则会提示报错
[root@db01 ~]# mongo localhost:27017
> use admin
switched to db admin
> db.shutdownServer()
server should be down...
2019-07-06T10:42:53.538+0800 I NETWORK [thread1] trying reconnect to localhost:27017 (127.0.0.1) 
failed
2019-07-06T10:42:53.538+0800 W NETWORK [thread1] Failed to connect to 127.0.0.1:27017, 
in(checking socket for error after poll), reason: Connection refused
2019-07-06T10:42:53.538+0800 I NETWORK [thread1] reconnect localhost:27017 (127.0.0.1) failed 
failed 
> 
bye
方法 2:启动命令添加--config 命令
[root@db01 ~]# mongod -f /opt/mongodb/conf/mongodb.conf --shutdown
killing process with pid: 3391

第5章 警告优化

5.1 普通用户登陆

高静内容:
2019-07-06T10:26:37.751+0800 I CONTROL [initandlisten] ** WARNING: You are running this process 
as the root user, which is not recommended.
解决方案:
1.创建普通用户
2.更改目录权限
3.切换到普通用户后再启动 mongo
[root@db01 ~]# useradd mongo
[root@db01 ~]# echo '123456'|passwd --stdin mongo
[root@db01 ~]# chown -R mongo:mongo /opt/mongo_cluster
[root@db01 ~]# chown -R mongo:mongo /data/mongo_cluster

5.2 关闭大内存页 hugepage

官方网站:
https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/
查看状态
[root@db01 ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
[root@db01 ~]# cat /sys/kernel/mm/transparent_hugepage/defrag 
[always] madvise never
临时关闭命令
[root@db01 ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled 
[root@db01 ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
永久关闭命令,用官方的脚本写入开机自启动
[root@db01 ~]# cat /etc/init.d/disable-transparent-hugepages
#!/bin/bash
### BEGIN INIT INFO
# Provides: disable-transparent-hugepages
# Required-Start: $local_fs
# Required-Stop:
# X-Start-Before: mongod mongodb-mms-automation-agent
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Disable Linux transparent huge pages
# Description: Disable Linux transparent huge pages, to improve
# database performance.
### END INIT INFO
case $1 in
 start)
 if [ -d /sys/kernel/mm/transparent_hugepage ]; then
 thp_path=/sys/kernel/mm/transparent_hugepage
 elif [ -d /sys/kernel/mm/redhat_transparent_hugepage ]; then
 thp_path=/sys/kernel/mm/redhat_transparent_hugepage
 else
 return 0
 fi
 echo 'never' > ${thp_path}/enabled
 echo 'never' > ${thp_path}/defrag
 re='^[0-1]+$'
 if [[ $(cat ${thp_path}/khugepaged/defrag) =~ $re ]]
 then
 # RHEL 7
 echo 0 > ${thp_path}/khugepaged/defrag
 else
 # RHEL 6
 echo 'no' > ${thp_path}/khugepaged/defrag
 fi
 unset re
 unset thp_path
 ;;
esac
赋予脚本权限
[root@db01 ~]# chmod 755 /etc/init.d/disable-transparent-hugepages 
加入开机自启动
[root@db01 ~]# chkconfig --add disable-transparent-hugepages
[root@db01 ~]# chkconfig --list|grep disable

5.3 内存占用超过 80%

2019-07-06T11:23:16.801+0800 I STORAGE [initandlisten] ** WARNING: The configured WiredTiger cache 
size is more than 80% of available RAM.
2019-07-06T11:23:16.801+0800 I STORAGE [initandlisten] ** See 
http://dochub.mongodb.org/core/faq-memory-diagnostics-wt
解决方法:
增加内存或者在配置文件里把 cash 调小
[mongo@db01 ~]$ grep "cacheSizeGB" /opt/mongo_cluster/mongo_27017/conf/mongodb.conf 
 cacheSizeGB: 1

5.4 用户访问控制

配置文件增加用户认证的配置参数
security: 
 authorization: enabled

5.5 relimit 警告

vim /etc/profile
ulimit -u 64000
source /etc/profile
重启 mongo 服务

第6章 mongodb 默认存在的库

test:登录时默认存在的库
admin 库:系统预留库,MongoDB 系统管理库
local 库:本地预留库,存储关键日志
config 库:MongoDB 配置信息库
操作命令:
show databases/show dbs
show tables/show collections
use admin
db/select database()

第7章 基本操作

7.1 介绍

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

7.2 显示命令

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 文件。

7.3 创建索引

默认情况下,创建索引将阻止数据库上的所有其他操作。在集合上构建索引时,保存集合的数据库对于读取或写
入操作是不可用的,直到索引构建完成。任何需要对所有数据库(例如 listDatabases)进行读或写锁定的操作将
等待前台索引构建完成。
对于可能需要长时间运行的索引创建操作,可以考虑 background 选项,这样 MongoDB 数据库在索引创建期
间仍然是可用的。例如,在 people 集合的 zipcode 键上创建一个索引,这个过程在后台运行,可以使用如下
方式:
db.people.createIndex( { zipcode: 1}, {background: true} )
默认 MongoDB 索引创建的 background 是 false 。
索引优化: db.test.find({"id":100}).explain()
db.people.createIndex( { zipcode: 1}, {background: true} )
db.inventory.find( { qty: { $lt: 30 } } )
>db.test.find({"age":{ $lt: 30 }})
{ "_id" : ObjectId("5cd60b69082200657d67d78a"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cd60b69082200657d67d78b"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cd60b69082200657d67d78c"), "name" : "yazhang", "age" : 28, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cd60b69082200657d67d78d"), "name" : "xiaozhang", "age" : 28, "ad" : "北京市朝阳区
" }
{ "_id" : ObjectId("5cd60b69082200657d67d78e"), "name" : "xiaozhang", "age" : 28, "ad" : "北京市朝阳区", 
"sex" : "boy" }
> db.test.find({"age":{ $lt: 30 }}).explain()
{
 "queryPlanner" : {
 "plannerVersion" : 1,
 "namespace" : "test.test",
 "indexFilterSet" : false,
 "parsedQuery" : {
 "age" : {
 "$lt" : 30
 }
 },
 "winningPlan" : {
 "stage" : "COLLSCAN",
 "filter" : {
 "age" : {
 "$lt" : 30
 }
 },
 "direction" : "forward"
 },
 "rejectedPlans" : [ ]
 },
 "serverInfo" : {
 "host" : "mongo01",
 "port" : 27017,
 "version" : "3.4.20",
 "gitVersion" : "447847d93d6e0a21b018d5df45528e815c7c13d8"
 },
 "ok" : 1
}
创建索引
> db.test.createIndex( { age: 1 } )
{
 "createdCollectionAutomatically" : false,
 "numIndexesBefore" : 2,
 "numIndexesAfter" : 3,
 "ok" : 1
}
查看索引
> db.test.getIndexes()
[
 {
 "v" : 2,
 "key" : {
 "_id" : 1
 },
 "name" : "_id_",
 "ns" : "test.test"
 },
 {
 "v" : 2,
 "key" : {
 "age" : 1
 },
 "name" : "age_1",
 "ns" : "test.test"
 }
]
再次查看执行计划
> db.test.find({"age":{ $lt: 30 }}).explain()
{
 "queryPlanner" : {
 "plannerVersion" : 1,
 "namespace" : "test.test",
 "indexFilterSet" : false,
 "parsedQuery" : {
 "age" : {
 "$lt" : 30
  }
  },
  "winningPlan" : {
  "stage" : "FETCH",
  "inputStage" : {
  "stage" : "IXSCAN",
"keyPattern" : {
  "age" : 1
  },
"indexName" : "age_1",
"isMultiKey" : false,
"multiKeyPaths" : {
  "age" : [ ]
  },
  "isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
  "direction" : "forward",
  "indexBounds" : {
  "age" : [
  "[-inf.0, 30.0)"
  ]
  }
  }
  },
  "rejectedPlans" : [ ]
  },
  "serverInfo" : {
  "host" : "mongo01",
  "port" : 27017,
  "version" : "3.4.20",
  "gitVersion" : "447847d93d6e0a21b018d5df45528e815c7c13d8"
  },
  "ok" : 1
}
删除索引
> db.test.dropIndex({ name: 1 }
{ "nIndexesWas" : 3, "ok" : 1 }

7.4 插入数据

7.4.1 官方文档

https://docs.mongodb.com/guides/server/read_queries/

7.4.2 单行插入
命令集合
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.insert({"name":"yazhang","age":28,"ad":"北京市朝阳区"})
db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区"})
db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区","sex":"boy"})
执行结果;
> db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
WriteResult({ "nInserted" : 1 })
> db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
WriteResult({ "nInserted" : 1 })
> db.test.insert({"name":"yazhang","age":28,"ad":"北京市朝阳区"})
WriteResult({ "nInserted" : 1 })
> db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区"})
WriteResult({ "nInserted" : 1 })
> db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区","sex":"boy"})
WriteResult({ "nInserted" : 1 })
7.4.3 多行插入
官网举例命令集合:
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" }
]);
执行过程:
> 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" }
... ]);
{
 "acknowledged" : true,
 "insertedIds" : [
 ObjectId("5cd60d2c082200657d67d78f"),
 ObjectId("5cd60d2c082200657d67d790"),
 ObjectId("5cd60d2c082200657d67d791"),
 ObjectId("5cd60d2c082200657d67d792"),
 ObjectId("5cd60d2c082200657d67d793")
 ]
}

7.5 查询数据

7.5.1 查询所有
> db.test.find()
{ "_id" : ObjectId("5cd60b69082200657d67d78a"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cd60b69082200657d67d78b"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cd60b69082200657d67d78c"), "name" : "yazhang", "age" : 28, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5cd60b69082200657d67d78d"), "name" : "xiaozhang", "age" : 28, "ad" : "北京市朝阳区
" }
{ "_id" : ObjectId("5cd60b69082200657d67d78e"), "name" : "xiaozhang", "age" : 28, "ad" : "北京市朝阳区", 
"sex" : "boy" }
7.5.2 查询单条
> db.test.findOne()
{
 "_id" : ObjectId("5cd60b69082200657d67d78a"),
 "name" : "zhangya",
 "age" : 27,
 "ad" : "北京市朝阳区"
}
7.5.3 条件查询
官网举例 1:
> myCursor = db.inventory.find( { status: "D" } )
{ "_id" : ObjectId("5cd60d2c082200657d67d791"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, 
"uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("5cd60d2c082200657d67d792"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 
30, "uom" : "cm" }, "status" : "D" }
官网举例 2:
> myCursor = db.inventory.find( { "size.uom": "in" } )
{ "_id" : ObjectId("5cd60d2c082200657d67d790"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 
11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5cd60d2c082200657d67d791"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, 
"uom" : "in" }, "status" : "D" }
官网举例 3: and
> myCursor = db.inventory.find( { status: "A", qty: { $lt: 30 } } )
{ "_id" : ObjectId("5cd60d2c082200657d67d78f"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, 
"uom" : "cm" }, "status" : "A" }
官网举例 4: or
> myCursor = db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
{ "_id" : ObjectId("5cd60d2c082200657d67d78f"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, 
"uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5cd60d2c082200657d67d790"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 
11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5cd60d2c082200657d67d793"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 
15.25, "uom" : "cm" }, "status" : "A" }
官网举例 5: 正则
myCursor = db.inventory.find( {status: "A",$or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]} )
或者:
myCursor = db.inventory.find( {
 status: "A",
 $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} )
返回结果
> myCursor = db.inventory.find( {
... status: "A",
... $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
... } )
{ "_id" : ObjectId("5cd60d2c082200657d67d78f"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, 
"uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5cd60d2c082200657d67d793"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 
15.25, "uom" : "cm" }, "status" : "A" }
>
7.5.4 查看数据库命令
> 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

7.6 更新数据

7.6.1 跟新单个文档
命令:
db.inventory.updateOne(
 { "item" : "paper" }, // specifies the document to update
 {
 $set: { "size.uom" : "cm", "status" : "P" },
 $currentDate: { "lastModified": true }
 }
)
执行结果;
> db.inventory.updateOne(
... { "item" : "paper" }, // specifies the document to update
... {
... $set: { "size.uom" : "cm", "status" : "P" },
... $currentDate: { "lastModified": true }
... }
... )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
查看数据
> myCursor = db.inventory.find( { "item": "paper" } )
{ "_id" : ObjectId("5cd60d2c082200657d67d791"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, 
"uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-05-10T23:56:18.954Z") }
7.6.2 更新多条数据
执行命令:
db.inventory.updateMany(
 { "qty" : { $lt: 50 } }, // specifies the documents to update
 {
 $set: { "size.uom" : "cm", "status": "P" },
 $currentDate : { "lastModified": true }
 }
)
执行结果:
> db.inventory.updateMany(
... { "qty" : { $lt: 50 } }, // specifies the documents to update
... {
... $set: { "size.uom" : "cm", "status": "P" },
... $currentDate : { "lastModified": true }
... }
... )
{ "acknowledged" : true, "matchedCount" : 2, "modifiedCount" : 2 }
查看数据
> myCursor = db.inventory.find( { "qty": { $lt: 50 } } )
{ "_id" : ObjectId("5cd60d2c082200657d67d78f"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, 
"uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-05-10T23:59:01.922Z") }
{ "_id" : ObjectId("5cd60d2c082200657d67d793"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 
15.25, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-05-10T23:59:01.922Z") }

7.7 删除数据

7.7.1 删除单条文档

官方文档:https://docs.mongodb.com/guides/server/delete/

查询结果
> myCursor = db.inventory.find( { "status": "D" } )
{ "_id" : ObjectId("5cd60d2c082200657d67d792"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 
30, "uom" : "cm" }, "status" : "D" }
操作命令
use test
db.inventory.deleteOne(
 { "status": "D" } // specifies the document to delete
)
返回结果
> db.inventory.deleteOne(
... { "status": "D" } // specifies the document to delete
... )
{ "acknowledged" : true, "deletedCount" : 1 }
再次查询
> myCursor = db.inventory.find( { "status": "D" } )
>
7.7.2 删除多条文档
查询数据
> myCursor = db.inventory.find( { "status": "P" } )
{ "_id" : ObjectId("5cd60d2c082200657d67d78f"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, 
"uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-05-10T23:59:01.922Z") }
{ "_id" : ObjectId("5cd60d2c082200657d67d791"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, 
"uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-05-10T23:56:18.954Z") }
{ "_id" : ObjectId("5cd60d2c082200657d67d793"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 
15.25, "uom" : "cm" }, "status" : "P", "lastModified" : ISODate("2019-05-10T23:59:01.922Z") }
操作命令
db.inventory.deleteMany(
 { "status" : "P" } // specifies the documents to delete
)
返回结果
> db.inventory.deleteMany(
... { "status" : "P" } // specifies the documents to delete
... )
{ "acknowledged" : true, "deletedCount" : 3 }
再次查看数据
> myCursor = db.inventory.find( { "status": "P" } )
>

第8章 工具介绍

8.1 官网地址

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

8.2 mongod

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

8.3 mongos

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

8.4 Mongostat

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

8.5 Mongotop

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

8.6 Mongooplog

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

8.7 Mongoperf

Mongoperf 是一种独立于 MongoDB 检查磁盘 I / O 性能的实用程序。它是随机磁盘 I / O 的测试并呈现结果。
例如:
echo "{nThreads:16, fileSizeMB:10000, r:true, w:true}"| mongoperf
在这个操作中:
mongoperf 测试直接物理随机读写 io 的,使用 16 个并发阅读器线程。
mongoperf 使用 10 GB 的测试文件。
或者参数写入文件里 mongoperf < config

第9章 授权认证

9.1 官方网址

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

9.2 授权介绍

用户管理界面
要添加用户, MongoDB 提供了该 db.createUser()方法。添加用户时,您可以为用户分配色以授予权限。
注意:
在数据库中创建的第一个用户应该是具有管理其他用户的权限的用户管理员。
您还可以更新现有用户,例如更改密码并授予或撤销角色。
操作命令
db.auth() 将用户验证到数据库。
db.changeUserPassword() 更改现有用户的密码。
db.createUser() 创建一个新用户。
db.dropUser() 删除单个用户。
db.dropAllUsers() 删除与数据库关联的所有用户。
db.getUser() 返回有关指定用户的信息。
db.getUsers() 返回有关与数据库关联的所有用户的信息。
db.grantRolesToUser() 授予用户角色及其特权。
db.removeUser() 已过时。从数据库中删除用户。
db.revokeRolesFromUser() 从用户中删除角色。
db.updateUser() 更新用户数据。

9.3 创建用户和角色

创建命令
[mongo@db01 ~]$ mongo db01:27017
> db.createUser({user: "admin",pwd: "123456",roles:[ { role: "root", db:"admin"}]})
Successfully added user: {
 "user" : "admin",
"roles" : [
 {
 "role" : "root",
 "db" : "admin"
 }
 ]
}
查看命令
> db.getUsers()
[
 {
 "_id" : "test.admin",
 "user" : "admin",
 "db" : "test",
 "roles" : [
 {
 "role" : "root",
"db" : "admin"
 }
 ]
 }
]
>

9.4 配置文件

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

9.5 使用账号密码连接

配置问权限认证后需要重启节点,再次登陆如果不使用账号密码就查看不了数据
[mongo@db01 ~]$ mongo db01:27017 
> show dbs
2019-07-06T11:43:14.047+0800 E QUERY [thread1] Error: listDatabases failed:{
 "ok" : 0,
 "errmsg" : "there are no users authenticated",
 "code" : 13,
 "codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:67:1
shellHelper.show@src/mongo/shell/utils.js:860:19
shellHelper@src/mongo/shell/utils.js:750:15
@(shellhelp2):1:1
使用账号密码登陆:
[mongo@db01 ~]$ mongo db01:27017 -u admin -p
MongoDB shell version v3.6.13
Enter password:
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
[mongo@db01 ~]$ mongo db01:27017 -u admin -p
Enter password: 
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
> db.test.find()
{ "_id" : ObjectId("5d2016396e91339718e18f95"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5d2016396e91339718e18f96"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5d2016396e91339718e18f97"), "name" : "yazhang", "age" : 28, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5d2016396e91339718e18f98"), "name" : "xiaozhang", "age" : 28, "ad" : "北京市朝阳区" }
{ "_id" : ObjectId("5d2016396e91339718e18f99"), "name" : "xiaozhang", "age" : 28, "ad" : "北京市朝阳区", 
"sex" : "boy" }
设置不同账号权限
use test
db.createUser(
 {
 user: "myTester",
 pwd: "xyz123",
 roles: [ { role: "readWrite", db: "test" },
 { role: "read", db: "test2" } ]
 }
)
执行结果
> db.createUser(
... {
... user: "myTester",
... pwd: "xyz123",
... roles: [ { role: "readWrite", db: "test" },
... { role: "read", db: "test2" } ]
... }
... )
Successfully added user: {
 "user" : "myTester",
 "roles" : [
 {
 "role" : "readWrite",
 "db" : "test"
 },
 {
 "role" : "read",
 "db" : "test2"
 }
 ]
}
登陆查看
> use test
switched to db test
> db.auth("myTester","xyz123")
1
> show collections
inventory
test
验证可读
> db.test.findOne()
{
 "_id" : ObjectId("5cd60b69082200657d67d78a"),
 "name" : "zhangya",
 "age" : 27,
 "ad" : "北京市朝阳区"
}
> db.inventory.findOne()
{
 "_id" : ObjectId("5cd638a71a9c2b8c9274568b"),
 "item" : "journal",
 "qty" : 25,
 "size" : {
 "h" : 14,
 "w" : 21,
 "uom" : "cm"
 },
 "status" : "A"
}
验证可写
> db.test.insertOne({"name":"xiaozhang","age":30,"ad":"北京市朝阳区"})
{
 "acknowledged" : true,
 "insertedId" : ObjectId("5cd63c5d5f928a68501b0bf0")
db.inventory.insertOne(
 { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)
切换到 test2 库,发现可读不可写
> use test2
> db.inventory.findOne()
{
 "_id" : ObjectId("5cd6392c1a9c2b8c92745690"),
 "item" : "journal",
 "qty" : 25,
 "size" : {
 "h" : 14,
 "w" : 21,
 "uom" : "cm"
 },
 "status" : "A"
}
> db.inventory.insertOne( { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: 
"cm" } } )
2019-05-11T11:24:05.120+0800 E QUERY [thread1] TypeError: err.hasWriteErrors is not a function :
DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:244:13
@(shell):1:1

第10章 副本集配置

10.1 官方网站

https://docs.mongodb.com/manual/tutorial/deploy-replica-set/

10.2 副本集介绍

image.png
image.png
image.png
image.png

10.3 目录规划

以/opt/mongo+端口号为单机多实例存放目录

10.4 创建多实例目录

[root@db01 ~]# mkdir -p /opt/mongo_cluster/mongo_2801{7,8,9}/{conf,logs,pid}
[root@db01 ~]# tree /opt/ -L 2
/opt/
├── mongodb -> mongodb-linux-x86_64-3.6.13
├── mongodb28017
│ ├── conf
│ ├── logs
│ └── pid
├── mongodb28018
│ ├── conf
│ ├── logs
│ └── pid
├── mongodb28019
│ ├── conf
│ ├── logs
│ └── pid
└── mongodb-linux-x86_64-3.6.13
 ├── bin
 ├── conf
 ├── LICENSE-Community.txt
 ├── logs
 ├── MPL-2
 ├── pid
 ├── README
 ├── THIRD-PARTY-NOTICES
 └── THIRD-PARTY-NOTICES.gotools
18 directories, 5 files

10.5 创建配置文件

[root@db01 ~]# cat >/opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf <<EOF
systemLog:
 destination: file 
 logAppend: true 
 path: /opt/mongo_cluster/mongo_28017/logs/mongodb.log
storage:
 journal:
 enabled: true
 dbPath: /data/mongo_cluster/mongo_28017
 directoryPerDB: true
 wiredTiger:
 engineConfig:
 cacheSizeGB: 0.5 
 directoryForIndexes: true
 collectionConfig:
 blockCompressor: zlib
 indexConfig:
 prefixCompression: true
processManagement:
 fork: true
pidFilePath: /opt/mongo_cluster/mongo_28017/pid/mongod.pid
net:
 port: 28017
 bindIp: 127.0.0.1,10.0.0.51
replication:
 oplogSizeMB: 1024 
 replSetName: dba58
EOF
[root@db01 ~]# cp /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf 
/opt/mongo_cluster/mongo_28018/conf/mongo_28018.conf
[root@db01 ~]# cp /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf 
/opt/mongo_cluster/mongo_28019/conf/mongo_28019.conf
[root@db01 ~]# sed -i 's#28017#28018#g' /opt/mongo_cluster/mongo_28018/conf/mongo_28018.conf 
[root@db01 ~]# sed -i 's#28017#28019#g' /opt/mongo_cluster/mongo_28019/conf/mongo_28019.conf

10.6 创建数据目录

[root@db01 ~]# mkdir /data/mongo_cluster/mongo_2801{7,8,9}
[root@db01 ~]# tree /data/ -L 1
/data/
├── mongodb
├── mongodb28017
├── mongodb28018
├── mongodb28019
└── soft

10.7 更改目录权限

[root@db01 ~]# chown -R mongo:mongo /data/mongo_cluster
[root@db01 ~]# chown -R mongo:mongo /opt/mongo_cluster

10.8 启动所有节点

[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf 
[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28018/conf/mongo_28018.conf 
[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28019/conf/mongo_28019.conf

10.9 初始化副本集

初始化命令:
config = {
_id : "dba58", 
members : [
{_id : 0, host : " db01:28017"},
{_id : 1, host : " db01:28018"},
{_id : 2, host : " db01:28019"},
] }
rs.initiate(config) 
执行过程
[mongo@db01 ~]$ mongo db01:28017 
> config = {
... _id : "dba58", 
... members : [
... {_id : 0, host : " db01:28017"},
... {_id : 1, host : " db01:28018"},
... {_id : 2, host : " db01:28019"},
... ] }
{
 "_id" : "dba58",
 "members" : [
 {
 "_id" : 0,
 "host" : " db01:28017"
 },
 {
 "_id" : 1,
 "host" : " db01:28018"
 },
 {
 "_id" : 2,
 "host" : " db01:28019"
 }
 ]
}
> rs.initiate(config) 
{
"ok" : 1,
 "operationTime" : Timestamp(1562403735, 1),
 "$clusterTime" : {
 "clusterTime" : Timestamp(1562403735, 1),
 "signature" : {
 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
 "keyId" : NumberLong(0)
 }
 }
}
dba58:SECONDARY> 
dba58:PRIMARY>

10.10 查看状态

dba58:PRIMARY> rs.status()

10.11 写入测试数据

命令:
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" }
]);
执行过程:
dba58:PRIMARY> 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" }
... ]);
{
 "acknowledged" : true,
 "insertedIds" : [
 ObjectId("5d20644ec990c165b34fcc58"),
ObjectId("5d20644ec990c165b34fcc59"),
 ObjectId("5d20644ec990c165b34fcc5a"),
 ObjectId("5d20644ec990c165b34fcc5b"),
 ObjectId("5d20644ec990c165b34fcc5c")
 ]
}
dba58:PRIMARY> db.inventory.find()
{ "_id" : ObjectId("5d20644ec990c165b34fcc58"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, 
"uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc59"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 
11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc5a"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, 
"uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc5b"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 
30, "uom" : "cm" }, "status" : "D" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc5c"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 
15.25, "uom" : "cm" }, "status" : "A" }

10.12 验证副本是否同步

dba58:SECONDARY> db.inventory.find()
Error: error: {
 "operationTime" : Timestamp(1562404003, 4),
 "ok" : 0,
 "errmsg" : "not master and slaveOk=false",
 "code" : 13435,
 "codeName" : "NotMasterNoSlaveOk",
 "$clusterTime" : {
 "clusterTime" : Timestamp(1562404003, 4),
 "signature" : {
 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
 "keyId" : NumberLong(0)
 }
 }
}
这里会提示副本不可读,通过命令配置副本可读
dba58:SECONDARY> rs.slaveOk();
再次查看
dba58:SECONDARY> db.inventory.find()
{ "_id" : ObjectId("5d20644ec990c165b34fcc58"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, 
"uom" : "cm" }, "status" : "A" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc59"), "item" : "notebook", "qty" : 50, "size" : { "h" : 8.5, "w" : 
11, "uom" : "in" }, "status" : "A" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc5b"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" : 
30, "uom" : "cm" }, "status" : "D" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc5a"), "item" : "paper", "qty" : 100, "size" : { "h" : 8.5, "w" : 11, 
"uom" : "in" }, "status" : "D" }
{ "_id" : ObjectId("5d20644ec990c165b34fcc5c"), "item" : "postcard", "qty" : 45, "size" : { "h" : 10, "w" : 
15.25, "uom" : "cm" }, "status" : "A" }
尝试删除
dba58:SECONDARY> db.inventory.remove({})
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })

10.13 故障转移

将主节点杀掉
[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf --
shutdown
killing process with pid: 3847
登陆副本节点查看
[mongo@db01 ~]$ mongo db01:28019
dba58:PRIMARY>
尝试修改数据
dba58:PRIMARY> db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
WriteResult({ "nInserted" : 1 })
dba58:PRIMARY> db.test.find()
{ "_id" : ObjectId("5d2091fc89c7e9177a03e785"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
在从库上查看
[mongo@db01 ~]$ mongo db01:28018
dba58:SECONDARY> rs.slaveOk();
dba58:SECONDARY> db.test.find()
{ "_id" : ObjectId("5d2091fc89c7e9177a03e785"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }
重新启动损坏节点
[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf
登陆查看数据
[mongo@db01 ~]$ mongo db01:28017
dba58:SECONDARY> rs.slaveOk();
dba58:SECONDARY> db.test.find()
{ "_id" : ObjectId("5d2091fc89c7e9177a03e785"), "name" : "zhangya", "age" : 27, "ad" : "北京市朝阳区" }

10.14 副本集权重调整

如果初始化进群的时候没有设置权重,那么默认每个节点的权重都是一样的,也就是说每个节点都
可以竞选主节点。

10.14.1 查看集群配置

[mongo@db01 ~]$ mongo db01:28019
dba58:PRIMARY> rs.conf()
{
 "_id" : "dba58",
 "version" : 1,
 "protocolVersion" : NumberLong(1),
 "members" : [
 {
 "_id" : 0,
 "host" : "db01:28017",
 "arbiterOnly" : false,
 "buildIndexes" : true,
 "hidden" : false,
 "priority" : 1,
 "tags" : {
 },
 "slaveDelay" : NumberLong(0),
 "votes" : 1
 },
 {
 "_id" : 1,
 "host" : "db01:28018",
 "arbiterOnly" : false,
 "buildIndexes" : true,
 "hidden" : false,
 "priority" : 1,
 "tags" : {
},
 "slaveDelay" : NumberLong(0),
 "votes" : 1
 },
 {
 "_id" : 2,
 "host" : "db01:28019",
 "arbiterOnly" : false,
 "buildIndexes" : true,
 "hidden" : false,
 "priority" : 1,
 "tags" : {
 },
 "slaveDelay" : NumberLong(0),
 "votes" : 1
 }
 ],
 "settings" : {
 "chainingAllowed" : true,
 "heartbeatIntervalMillis" : 2000,
 "heartbeatTimeoutSecs" : 10,
 "electionTimeoutMillis" : 10000,
 "catchUpTimeoutMillis" : -1,
 "catchUpTakeoverDelayMillis" : 30000,
 "getLastErrorModes" : {
 },
 "getLastErrorDefaults" : {
 "w" : 1,
 "wtimeout" : 0
 },
 "replicaSetId" : ObjectId("5d206397091c6674936c8cd7")
 }
}

10.14.2 调整节点权重

dba58:PRIMARY> config = rs.conf()
dba58:PRIMARY> config.members[0].priority=100
100
dba58:PRIMARY> rs.reconfig(config)
{
 "ok" : 1,
 "operationTime" : Timestamp(1562417568, 1),
 "$clusterTime" : {
 "clusterTime" : Timestamp(1562417568, 1),
 "signature" : {
 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
 "keyId" : NumberLong(0)
 }
 }
}
dba58:SECONDARY>

10.14.3 主节点主动降级

dba58:PRIMARY> rs.stepDown()

10.15 增加新节点

创建新节点目录及启动
[mongo@db01 ~]$ mkdir /opt/mongo_cluster/mongo_28010/{conf,logs,pid} -p
[mongo@db01 ~]$ mkdir /data/mongo_cluster/mongo_28010
[mongo@db01 ~]$ cp /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf 
/opt/mongo_cluster/mongo_28010/conf/mongo_28010.conf
[mongo@db01 ~]$ sed -i 's#28017#28010#g' 
/opt/mongo_cluster/mongo_28010/conf/mongo_28010.conf
[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28010/conf/mongo_28010.conf
[mongo@db01 ~]$ mongo db01:28010
>
增加新节点命令,主库操作
[mongo@db01 ~]$ mongo db01:28017
dba58:PRIMARY> use admin
dba58:PRIMARY> rs.add("db01:28010")
{
 "ok" : 1,
 "operationTime" : Timestamp(1562420341, 1),
 "$clusterTime" : {
 "clusterTime" : Timestamp(1562420341, 1),
"signature" : {
 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
 "keyId" : NumberLong(0)
 }
 }
}
查看新增加节点
[mongo@db01 ~]$ mongo db01:28010
dba58:SECONDARY>

10.16 删除旧节点

主节点操作
[mongo@db01 ~]$ mongo db01:28017
dba58:PRIMARY> rs.remove("db01:28010")
{
 "ok" : 1,
 "operationTime" : Timestamp(1562420521, 1),
 "$clusterTime" : {
 "clusterTime" : Timestamp(1562420521, 1),
 "signature" : {
 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
 "keyId" : NumberLong(0)
 }
 }
}
再次查看下线节点
[mongo@db01 ~]$ mongo db01:28010
dba58:OTHER>
现在可以关闭节点了
[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28010/conf/mongo_28010.conf --
shutdown

10.17 增加仲裁节点

官方地址:
https://docs.mongodb.com/manual/tutorial/add-replica-set-arbiter/

Arbiter 节点只参与投票,不能被选为 Primary,并且不从 Primary 同步数据。
清空 28010 节点的数据
[mongo@db01 ~]$ rm -rf /data/mongo_cluster/mongo_28010/*
重新启动
[mongo@db01 ~]$ mongod -f /opt/mongo_cluster/mongo_28010/conf/mongo_28010.conf
检查
[mongo@db01 ~]$ mongo db01:28010
主库操作
[mongo@db01 ~]$ mongo db01:28017
dba58:PRIMARY> rs.addArb("db01:28010")
{
 "ok" : 1,
 "operationTime" : Timestamp(1562421119, 1),
 "$clusterTime" : {
 "clusterTime" : Timestamp(1562421119, 1),
 "signature" : {
 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
 "keyId" : NumberLong(0)
 }
 }
}
查看集群状态
dba58:PRIMARY> rs.status()
.....................................................
{
 "_id" : 3,
 "name" : "db01:28010",
 "health" : 1,
 "state" : 7,
 "stateStr" : "ARBITER",
 "uptime" : 1305,
 "lastHeartbeat" : ISODate("2019-07-06T14:13:44.757Z"),
 "lastHeartbeatRecv" : ISODate("2019-07-06T14:13:44.735Z"),
 "pingMs" : NumberLong(0),
 "lastHeartbeatMessage" : "",
 "syncingTo" : "",
 "syncSourceHost" : "",
 "syncSourceId" : -1,
"infoMessage" : "",
 "configVersion" : 5
 }
查看节点状态
[mongo@db01 ~]$ mongo db01:28010
dba58:ARBITER>

第11章 备份恢复

11.1 备份恢复工具介绍

(1)mongoexport/mongoimport
(2)mongodump/mongorestore

11.2 备份工具区别在哪里?

应用场景总结:
1、异构平台迁移 mysql <---> mongodb
2、同平台,跨大版本:mongodb 2 ----> mongodb 3
mongoexport/mongoimport:json csv
日常备份恢复时使用.
mongodump/mongorestore

11.3 导出工具 mongoexport

mongoexport 具体用法如下所示:
$ mongoexport --help 
参数说明:
-h:指明数据库宿主机的 IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明 collection 的名字
-f:指明要导出那些列
-o:指明到要导出的文件名
-q:指明导出数据的过滤条件
--authenticationDatabase admin
举例:
1.单表备份至 json 格式
mongoexport --port 28017 -d dba -c inventory -o /backup/log.json
注:备份文件的名字可以自定义,默认导出了 JSON 格式的数据。
2. 单表备份至 csv 格式
如果我们需要导出 CSV 格式的数据,则需要使用----type=csv 参数:
mongoexport --port 28017 -d dba -c inventory --type=csv -f item,qty,size,status -o /backup/log.csv

11.4 导入工具

$ mongoimport --help
参数说明:
-h:指明数据库宿主机的 IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明 collection 的名字
-f:指明要导入那些列
-j, --numInsertionWorkers=<number> number of insert operations to run concurrently 
(defaults to 1)
//并行
数据恢复:
1.恢复 json 格式表数据到 log1
mongoimport --port 28017 -d oldboy -c inventory /backup/log.json
2.恢复 csv 格式的文件到 log2
上面演示的是导入 JSON 格式的文件中的内容,如果要导入 CSV 格式文件中的内容,则需要通过--type 参数指定导
入格式,具体如下所示:
错误的恢复
注意:
(1)csv 格式的文件头行,有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log2 --
type=csv --headerline --file /mongodb/log.csv
(2)csv 格式的文件头行,没有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log3 --
type=csv -f id,name,age,date --file /mongodb/log.csv
--headerline:指明第一行是列名,不需要导入。

11.5 异构平台迁移案例

1.安装数据库
[root@db01 ~]# yum install mariadb mariadb-server -y
2.开启安全路径
cat > /etc/my.cnf << EOF
secure-file-priv=/tmp
3.重启数据库
[root@db01 ~]# systemctl restart mariadb.service 
4.导入城市数据
[root@db01 ~]# mysql
MariaDB [(none)]> source /root/world.sql
5.将样本数据导出成 csv 格式
MariaDB [world]> select * from world.city into outfile '/tmp/city1.csv' fields terminated by ',';
6.查看表结构
MariaDB [(none)]> desc world.city;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| CountryCode | char(3) | NO | MUL | | |
| District | char(20) | NO | | | |
| Population | int(11) | NO | | 0 | |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
7.处理备份文件
vim /tmp/city.csv ### 添加第一行列名信息
ID,Name,CountryCode,District,Population
8.在 mongodb 中导入备份
[root@db01 ~]# su - mongo
[mongo@db01 ~]$ mongoimport --port 28017 -d world -c city --type=csv -f 
ID,Name,CountryCode,District,Population --file /tmp/city1.csv 
2019-07-07T21:00:26.473+0800 connected to: localhost:28017
2019-07-07T21:00:26.626+0800 imported 4080 documents
9.查看数据
[mongo@db01 ~]$ mongo db01:28017
dba58:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
local 0.001GB
test 0.000GB
world 0.000GB
dba58:PRIMARY> use world
switched to db world
dba58:PRIMARY> db.city.find({CountryCode:"CHN"});

11.6 mongodump 和 mongorestore

1.介绍:
mongodump 能够在 Mongodb 运行时进行备份,它的工作原理是对运行的 Mongodb 做查询,然后将所有查到的文档写
入磁盘。
但是存在的问题时使用 mongodump 产生的备份不一定是数据库的实时快照,如果我们在备份时对数据库进行了写
入操作,则备份出来的文件可能不完全和 Mongodb 实时数据相等。另外在备份时可能会对其它客户端性能产生不
利的影响。
2.使用方法:
$ mongodump --help
参数说明:
-h:指明数据库宿主机的 IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明 collection 的名字
-o:指明到要导出的文件名
-q:指明导出数据的过滤条件
-j, --numParallelCollections= number of collections to dump in parallel (4 by default)
--oplog 备份的同时备份 oplog
3.mongodump 和 mongorestore 基本使用
全库备份
[root@db01 ~]# mkdir /data/backup
[root@db01 ~]# chown -R mongo:mongo /data/backup/
[root@db01 ~]# su - mongo
[mongo@db01 ~]$ mongodump --port 28017 -o /data/backup
备份 word 库
[mongo@db01 ~]$ mongodump --port 28017 -d world -o /data/backup
压缩备份
[mongo@db01 ~]$ mongodump --port 28017 -o /data/backup --gzip
[mongo@db01 ~]$ mongodump --port 28017 -d world -o /data/backup --gzip
恢复 world 库
dba58:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
local 0.001GB
test 0.000GB
world 0.000GB
dba58:PRIMARY> use world
switched to db world
dba58:PRIMARY> db.dropDatabase()
..............
dba58:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
local 0.001GB
test 0.000GB
[mongo@db01 ~]$ mongorestore --port 28017 -d world1 /data/backup/world/
恢复之前先删掉
[mongo@db01 ~]$ mongorestore --port 28017 -d world1 /data/backup/world/ --drop

11.7 mongodump 和 mongorestore 高级企业应用(--oplog)

注意:这是 replica set 或者 master/slave 模式专用
1.oplog 介绍
在 replica set 中 oplog 是一个定容集合(capped collection),它的默认大小是磁盘空间的 5%(可以
通过--oplogSizeMB 参数修改).
位于 local 库的 db.oplog.rs,有兴趣可以看看里面到底有些什么内容。
其中记录的是整个 mongodb 实例一段时间内数据库的所有变更(插入/更新/删除)操作。
当空间用完时新记录自动覆盖最老的记录。
其覆盖范围被称作 oplog 时间窗口。需要注意的是,因为 oplog 是一个定容集合,
所以时间窗口能覆盖的范围会因为你单位时间内的更新次数不同而变化。
想要查看当前的 oplog 时间窗口预计值,可以使用以下命令:
dba58:PRIMARY> use local
dba58:PRIMARY> db.oplog.rs.find().pretty()
..................................
"ts" : Timestamp(1562403898, 1),
"op" : "n"
"o" :
"i": insert
"u": update
"d": delete
"c": db cmd
..................................
dba58:PRIMARY> rs.printReplicationInfo()
configured oplog size: 1024MB #集合大小
log length start to end: 104539secs (29.04hrs) #预计窗口覆盖时间
oplog first event time: Sat Jul 06 2019 17:02:15 GMT+0800 (CST)
oplog last event time: Sun Jul 07 2019 22:04:34 GMT+0800 (CST)
now: Sun Jul 07 2019 22:04:38 GMT+0800 (CST)
2. oplog 企业级应用
(1)实现热备,在备份时使用--oplog 选项
注:为了演示效果我们在备份过程,模拟数据插入
(2)准备测试数据
[mongo@db01 ~]$ mongo db01:28017
dba58:PRIMARY> use oldboy
switched to db oldboy
dba58:PRIMARY> for(var i = 1 ;i < 100; i++) {
 db.foo.insert({a:i});
}
dba58:PRIMARY> use local
dba58:PRIMARY> db.oplog.rs.find({"op":"i"}).pretty()
(3) oplog 配合 mongodump 实现热备
作用介绍:--oplog 会记录备份过程中的数据变化。会以 oplog.bson 保存下来
[mongo@db01 ~]$ mongodump --port 28017 --oplog -o /data/backup
恢复
[mongo@db01 ~]$ mongorestore --port 28017 --oplogReplay /data/backup --drop

11.8 oplog 高级应用

背景:每天 0 点全备,oplog 恢复窗口为 48 小时
某天,上午 10 点 world.city 业务表被误删除。
恢复思路:
0、停应用
2、找测试库
3、恢复昨天晚上全备
4、截取全备之后到 world.city 误删除时间点的 oplog,并恢复到测试库
5、将误删除表导出,恢复到生产库
恢复步骤:
模拟故障环境:
1、全备数据库
模拟原始数据
[mongo@db01 ~]$ mongo db01:28017
dba58:PRIMARY> use wo
dba58:PRIMARY> for(var i = 1 ;i < 20; i++) {
 db.ci.insert({a: i});
}
2.全备
[mongo@db01 ~]$ rm -rf /data/backup/*
[mongo@db01 ~]$ mongodump --port 28017 --oplog -o /data/backup
--oplog 功能:在备份同时,将备份过程中产生的日志进行备份
文件必须存放在/data/backup 下,自动命令为 oplog.bson
3.再次模拟数据
[mongo@db01 ~]$ mongo db01:28017
dba58:PRIMARY> use wo
dba58:PRIMARY> db.ci1.insert({id:1})
dba58:PRIMARY> db.ci2.insert({id:2})
dba58:PRIMARY> show tables
ci
ci1
ci2
4.上午 10 点:删除 wo 库下的 ci 表
10:00 时刻,误删除
dba58:PRIMARY> db.ci.drop()
true
dba58:PRIMARY> show tables
ci1
ci2
5.备份现有的 oplog.rs 表
[mongo@db01 ~]$ mongodump --port 28017 -d local -c oplog.rs -o /data/backup
6.截取 oplog 并恢复到 drop 之前的位置
更合理的方法:登陆到原数据库
[mongo@db01 ~]$ mongo db01:28017 
dba58:PRIMARY> use local
dba58:PRIMARY> db.oplog.rs.find({ns:"wo.$cmd"}).pretty();
{
 "ts" : Timestamp(1562510676, 1),
 "t" : NumberLong(20),
 "h" : NumberLong("-6833353909054714034"),
 "v" : 2,
"op" : "c",
 "ns" : "wo.$cmd",
 "ui" : UUID("327876dd-5032-4914-a080-58707e0cd867"),
 "wall" : ISODate("2019-07-07T14:44:36.031Z"),
 "o" : {
 "drop" : "ci"
 }
}
7.恢复备份+应用 oplog
[mongo@db01 ~]$ cd /data/backup/local/
[mongo@db01 /data/backup/local]$ ls
oplog.rs.bson oplog.rs.metadata.json
[mongo@db01 /data/backup/local]$ cp oplog.rs.bson ../oplog.bson
[mongo@db01 /data/backup/local]$ rm -rf /data/backup/local/
[mongo@db01 ~]$ mongorestore --port 28017 --oplogReplay --oplogLimit "1562510676:1" --drop 
/data/backup/
[mongo@db01 ~]$ mongo db01:28017 
dba58:PRIMARY> use wo
switched to db wo
dba58:PRIMARY> show tables
ci
ci1
ci2

第12章 升级步骤

1.首先确保是副本集状态
2.先关闭 1 个副本节点
3.检测数据是否可以升级
4.升级副本节点的可执行文件
5.更新配置文件
6.启动升级后的副本节点
7.确保集群工作正常
8.滚动升级其他副本节点
9.最后主节点降级
10.确保集群 可用
11.关闭降级的老的主节12.升级老的主节点
13.重新加入集群
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容