文章目录

  • NoSQL介绍
    • NoSQL简介
    • 什么是NoSQL
    • 为什么使用NoSQL
  • MongoDB简介
    • MongoDB数据格式
      • JSON
      • BSON
    • MongoDB包含的程序
  • 应用场景
  • 安装部署
    • 官方文档
    • 安装方式
    • 目录规划
    • 软件安装
    • 配置文件
    • 启动关闭
      • 启动命令
      • 检查命令
      • 写入环境变量
      • 创建hosts解析
      • 连接命令
      • 关闭命令
  • 警告优化
    • 普通用户登录
    • 关闭大内存页hugepage
    • 内存占用超过80%
    • 用户访问控制
  • mongodb默认存在的库
  • 基本操作
    • 介绍
    • 显示命令
    • 创建索引
    • 插入数据
      • 官方文档
    • 单行插入
      • 多行插入
    • 查询数据
      • 查询所有
      • 查询单条
      • 条件查询
      • 查看数据库命令
    • 更新数据
      • 更新单个文档
      • 更新多条数据
    • 删除数据
      • 删除单条文档
      • 删除多条文档
  • 工具介绍
    • 官网地址
    • mongod
    • mongos
    • mongostat
    • Mongotop
    • Mongooplog
    • Mongooplog
  • 授权认证
    • 官方网址
    • 授权介绍
    • 创建用户和角色
    • 配置文件
    • 使用账号密码连接
  • 副本集配置
    • 官方网站
    • 副本集介绍
    • 目录规划
    • 创建多实例目录
    • 创建配置文件
    • 创建数据目录
    • 更改目录权限
    • 启动所有节点
    • 初始化副本集
    • 查看状态
    • 写入测试数据
    • 验证副本是否同步
    • 故障转移
    • 副本集权重调整
      • 查看集群配置
      • 调整节点权重
      • 主节点主动降级
    • 增加新节点
    • 删除旧节点
    • 增加仲裁节点
  • 备份恢复
    • 备份恢复工具介绍
    • 备份工具区别在哪里
    • 导出工具mongoexport
    • 导入工具
    • 异构平台迁移案例
    • mongodump和mongorestore
    • mongodump和mongorestore高级企业应用(--oplog)
    • oplog高级应用
  • 升级步骤
    • oplog高级应用
  • 升级步骤

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 存储引擎(原先需要3台服务器,一压缩只要2台就够了)和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。

应用场景

#增加字段可直接增加,随意扩展,而不需要alter(mysql)
链接: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.logstorage:journal:enabled: truedbPath: /data/mongo_cluster/mongo_27017directoryPerDB: truewiredTiger:engineConfig:cacheSizeGB: 1directoryForIndexes: truecollectionConfig:blockCompressor: zlibindexConfig:prefixCompression: trueprocessManagement:fork: truepidFilePath: /opt/mongo_cluster/mongo_27017/pid/mongod.pidnet:port: 27017bindIp: 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
方法2:
解决方法2:创建systemcd启动文件
cat >/lib/systemd/system/mongod.service<<EOF
[Unit]
Description=MongoDB Database Server
Documentation=https://docs.mongodb.org/manual
After=network.target[Service]
User=mongod
Group=mongod
Environment="OPTIONS=-f /opt/mongo_27017/conf/mongodb.conf"
ExecStart=/opt/mongodb/bin/mongod \$OPTIONS
ExecStartPre=/usr/bin/chown -R mongod:mongod /opt/mongo_27017
ExecStartPre=/usr/bin/chown -R mongod:mongod /data/mongo_27017
PermissionsStartOnly=true
PIDFile=/opt/mongo_27017/pid/mongod.pid
Type=forking
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for for mongod as specified in
# http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings[Install]
WantedBy=multi-user.target
EOFuseradd mongod -M -s /sbin/nologin
systemctl daemon-reload
systemctl start mongod

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

副本集介绍




目录规划

以/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 lcc -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 lcc -c log1
/mongodb/log.json
2.恢复csv 格式的文件到log2
上面演示的是导入JSON 格式的文件中的内容,如果要导入CSV 格式文件中的内容,则需要通过--type 参数指定导
入格式,具体如下所示:
错误的恢复
注意:
(1)csv 格式的文件头行,有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d lcc -c log2 --
type=csv --headerline --file /mongodb/log.csv
(2)csv 格式的文件头行,没有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d lcc -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 lcc
switched to db lcc
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.重新加入集群

``

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.重新加入集群

mogodb 基础与副本集(详细)相关推荐

  1. MongoDB:高可用基础-副本集原理

    文章目录 1.副本集介绍 2.Raft核心流程 3.副本集选举 4.副本集数据复制 5.副本集故障转移 1.副本集介绍 在生产环境中,不建议使用单机版的MongoDB服务器,因为有可能出现单点问题: ...

  2. MongoDB副本集搭建(超级详细)

    MongoDB 副本集原理 什么是复制 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,并可以保证数据的安全性 复制还允许从硬件故障和服务中断中恢复数据 为什么要复制 数据 ...

  3. Kubernetes控制器--副本集ReplicaSet

    Kubernetes最核心的功能就是编排,而编排操作都是依靠控制器对象来完成的,高级的控制器对象控制基础的控制器对象,基础的控制器对象再去控制Pod,Pod里面再包容器.Kubernetes项目里AP ...

  4. MongoDB副本集学习(一):概述和环境搭建

    MongoDB副本集概述 以下图片摘自MongoDB官方文档:http://docs.mongodb.org/manual/core/replication-introduction/ Primary ...

  5. mongodb集群-副本集(CSRS)

    一.概述 (1)MongoDB复制是将数据同步在多个服务器的过程. (2)复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性. (3)复制还允许您从硬 ...

  6. MongoDB高性能、高可用之副本集、读写分离、分片、操作实践

    2019独角兽企业重金招聘Python工程师标准>>> 关于MongoDb 1.MongoDB是一个开源的.基于分布式的.面向文档存储的非关系型数据库. 2.是非关系型数据库当中功能 ...

  7. MongoDB之副本集配置

    MongoDB主从复制 主从复制是 MongoDB 最早使用的复制方式, 该复制方式易于配置,并且可以支持任意数量的从节点服务器,与使用单节点模式相比有如下优点: 在从服务器上存储数据副本,提高了数据 ...

  8. 《Linux运维实战:Centos7.6一键离线部署mongodb4.2.23副本集群》

    一.部署背景 由于业务系统的特殊性,我们需要面向不通的客户安装我们的业务系统,而作为基础组件中的mongodb针对不同的客户环境需要多次部署,作为一个运维工程师,提升工作效率也是工作中的重要一环.所以 ...

  9. 2.MongoDB 4.2副本集环境基于时间点的恢复

    (一)MongoDB恢复概述 对于任何数据库,如果要将数据库恢复到过去的任意时间点,否需要有过去某个时间点的全备+全备之后的重做日志. 接下来根据瑞丽航空的情况进行概述: 全备:每天晚上都会进行备份: ...

最新文章

  1. MVC中实现多按钮提交(转)
  2. 超详细的Java常用时间操作工具类
  3. Android实现CoverFlow效果
  4. hdu 2074 叠框
  5. android Formatter 的使用
  6. mysql all 授权_mysql给数据库授权 GRANT ALL PRIVILEGES ON
  7. Multilink ppp多链接PPP协议的配置
  8. hibernate session 新增、删除,修改、查询样例
  9. linux查看网卡物理编号_Centos 网卡命名规范及信息查看(物理网卡,虚拟网卡)...
  10. 剪纸窗花PSD分层素材|春节的常见元素,轻松应用到海报设计
  11. ui做成html格式,使用element-ui的table组件时,渲染为html格式
  12. 【转】Tomcat总体结构(Tomcat源代码阅读系列之二)
  13. linux python安装pip_linux安装pip2.7
  14. 服务器搬迁方案_IT机房搬迁 实施方案
  15. ListView刷新指定位置的item
  16. matlab人机交互界面设计
  17. 数学期望、方差、标准差
  18. Visual Studio Ultimate 2015 旗舰版 Preview
  19. 无视硬件检测直接运行Win10混合现实门户
  20. restTemplate请求设置请求头信息

热门文章

  1. 什么是同源策略,所带来的影响
  2. 鼠标滚轮控制横向滚动条
  3. React实现(Web端)网易云音乐项目(一),错过了真的可惜呀
  4. substr函数c语言实现,substr是什么函数?怎么用
  5. vue 点击遮罩层功能区以外的地方关闭遮罩层
  6. WEB——HTML、CSS、javascript
  7. 毕业设计- 基于单片机与GPS+GSM的车辆定位跟踪系统
  8. 32岁转行0基础学Html5,30岁没学历从零开始学什么好,30岁改行的5个职业
  9. JS对全角与半角的验证,相互转化以及介绍 | CSDN创作打卡
  10. 网页设计期末作业ppt+源码(免费获取)