mogodb应用

NoSQL介绍

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
的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是
一种全新的思维的注入。

什么是NoSQL

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

为什么使用NoSQL

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

MongoDB简介

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

MongoDB数据格式

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 获取,字段值的类型可以是 数字、字符串、数组、对象几种。

BSON


MongoDB特点

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

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。

应用场景

作者:阿里云云栖号
链接:https://www.zhihu.com/question/32071167/answer/147896283
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

案例1用在应用服务器的日志记录,查找起来比文本灵活,导出也很方便。也是给应用练手,从外围系统开始使用MongoDB。
用在一些第三方信息的获取或者抓取,因为MongoDB的schema-less,所有格式灵活,不用为了各种格式不一样的信息专门设计统一的格式,极大的减少开发的工作。案例2mongodb之前有用过,主要用来存储一些监控数据,No schema 对开发人员来说,真的很方便,增加字段不用改表结构,而且学习成本极低。案例3使用MongoDB做了O2O快递应用,·将送快递骑手、快递商家的信息(包含位置信息)存储在 MongoDB,然后通过 MongoDB 的地理位置查询,这样很方便的实现了查找附近的商家、骑手等功能,使得快递骑手能就近接单,目前在使用MongoDB 上没遇到啥大的问题,官网的文档比较详细,很给力。经常跟一些同学讨论 MongoDB 业务场景时,会听到类似『你这个场景 mysql 也能解决,没必要一定用 MongoDB』的声音,的确,并没有某个业务场景必须要使用 MongoDB才能解决,但使用 MongoDB 通常能让你以更低的成本解决问题(包括学习、开发、运维等成本),下面是 MongoDB 的主要特性,大家可以对照自己的业务需求看看,匹配的越多,用 MongoDB 就越合适。MongoDB 特性优势事务支持MongoDB 目前只支持单文档事务,需要复杂事务支持的场景暂时不适合灵活的文档模型JSON 格式存储最接近真实对象模型,对开发者友好,方便快速开发迭代高可用复制集满足数据高可靠、服务高可用的需求,运维简单,故障自动切换可扩展分片集群海量数据存储,服务能力水平扩展高性能mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求强大的索引支持地理位置索引可用于构建 各种 O2O 应用、文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求Gridfs解决文件存储的需求aggregation & mapreduce解决数据分析场景需求,用户可以自己写查询语句或脚本,将请求都分发到 MongoDB 上完成从目前阿里云 MongoDB 云数据库上的用户看,MongoDB 的应用已经渗透到各个领域,比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例。游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析视频直播,使用 MongoDB 存储用户信息、礼物信息等......如果你还在为是否应该使用 MongoDB,不如来做几个选择题来辅助决策(注:以下内容改编自 MongoDB 公司 TJ 同学的某次公开技术分享)。应用特征Yes / No应用不需要事务及复杂 join 支持必须 Yes新应用,需求会变,数据模型无法确定,想快速迭代开发?应用需要2000-3000以上的读写QPS(更高也可以)?应用需要TB甚至 PB 级别数据存储?应用发展迅速,需要能快速水平扩展?应用要求存储的数据不丢失?应用需要99.999%高可用?应用需要大量的地理位置查询、文本查询?如果上述有1个 Yes,可以考虑 MongoDB,2个及以上的 Yes,选择MongoDB绝不会后悔。

安装部署

官方文档

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

安装方式

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

目录规划

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

软件安装

[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

配置文件

参考博客
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/monogdb.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

启动关闭

启动命令

[root@db01 ~]# /opt/mongodb/bin/mongod -f /opt/mongodb/conf/monogdb.conf
about to fork child process, waiting until server is ready for connections.
forked process: 3024
child process started successfully, parent exiting

检查命令

[root@db01 ~]# ps -ef|grep mongo
root 3024 1 3 10:26 ? 00:00:00 /opt/mongodb/bin/mongod -f
/opt/mongodb/conf/monogdb.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

写入环境变量

[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

创建hosts解析

[root@db01 ~]# cat > /etc/hosts <<EOF
10.0.0.51 db01
10.0.0.52 db02
10.0.0.53 db03
EOF

连接命令

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]
>

关闭命令

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/monogdb.conf --shutdown
killing process with pid: 3391

警告优化

普通用户登录

高静内容:
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

关闭大内存页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

内存占用超过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/monogdb.conf
cacheSizeGB: 1

用户访问控制

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

mongodb默认存在的库

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

基本操作

介绍

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 中的所有写操作都是在单个文档的级别上
进行的

显示命令

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

创建索引

默认情况下,创建索引将阻止数据库上的所有其他操作。在集合上构建索引时,保存集合的数据库对于读取或写
入操作是不可用的,直到索引构建完成。任何需要对所有数据库(例如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 }

插入数据

官方文档

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

单行插入

命令集合
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 })

多行插入

官网举例命令集合:
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")
]
}

查询数据

查询所有

> 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" }

查询单条

> db.test.findOne()
{
"_id" : ObjectId("5cd60b69082200657d67d78a"),
"name" : "zhangya",
"age" : 27,
"ad" : "北京市朝阳区"
}

条件查询

官网举例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" }
> db.inventory.find( { "size.h":{$gt:10}, "qty":75 } )
{ "_id" : ObjectId("5d22c9c03c6524dfb1de89b5"), "item" : "planner", "qty" : 75, "size" : { "h" : 22.85, "w" :
30, "uom" : "cm" }, "status" : "D" }
官网举例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" }
>

查看数据库命令

> 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

更新数据

更新单个文档

命令:
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") }

更新多条数据

执行命令:
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") }

删除数据

删除单条文档

官方文档
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" } )
>

删除多条文档

查询数据
> 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" } )
>

工具介绍

官网地址

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

mongod

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

mongos

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

mongostat

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

Mongotop

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

Mongooplog

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

Mongooplog

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

授权认证

官方网址

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

授权介绍

用户管理界面
要添加用户, 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() 更新用户数据。

创建用户和角色

创建命令
[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"
}
]
}
]
>

配置文件

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

使用账号密码连接

配置问权限认证后需要重启节点,再次登陆如果不使用账号密码就查看不了数据
[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

副本集配置

官方网站

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

副本集介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I18ZiPzp-1576240067786)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1576215977073.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmBRbRtK-1576240067796)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1576216014315.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5uuBdUzL-1576240067799)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1576216038288.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NUiRHJj5-1576240067801)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1576216070467.png)]

目录规划

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

创建多实例目录

[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

创建配置文件

[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
security:
authorization: enabled
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

创建数据目录

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

更改目录权限

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

启动所有节点

[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

初始化副本集

初始化命令:
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>

查看状态

dba58:PRIMARY> rs.status()

写入测试数据

命令:
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" }

验证副本是否同步

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" } })

故障转移

将主节点杀掉
[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" : "北京市朝阳区" }

副本集权重调整

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

查看集群配置

[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")
}
}

调整节点权重

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>

主节点主动降级

dba58:PRIMARY> rs.stepDown()

增加新节点

创建新节点目录及启动
[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>

删除旧节点

主节点操作
[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

增加仲裁节点

官方地址:
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>

备份恢复

备份恢复工具介绍

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

备份工具区别在哪里

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

导出工具mongoexport

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

导入工具

$ 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 -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log1
/mongodb/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:指明第一行是列名,不需要导入。

异构平台迁移案例

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"});

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

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

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

升级步骤

1.首先确保是副本集状态
2.先关闭1 个副本节点
3.检测数据是否可以升级
4.升级副本节点的可执行文件
5.更新配置文件
6.启动升级后的副本节点
7.确保集群工作正常
8.滚动升级其他副本节点
9.最后主节点降级
10.确保集群 可用
11.关闭降级的老的主节点
12.升级老的主节点
13.重新加入集群

口为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.KaTeX parse error: Expected 'EOF', got '}' at position 5: cmd"}̲).pretty(); { "…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


# 升级步骤

1.首先确保是副本集状态
2.先关闭1 个副本节点
3.检测数据是否可以升级
4.升级副本节点的可执行文件
5.更新配置文件
6.启动升级后的副本节点
7.确保集群工作正常
8.滚动升级其他副本节点
9.最后主节点降级
10.确保集群 可用
11.关闭降级的老的主节点
12.升级老的主节点
13.重新加入集群


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值