MongoDB 入门基础知识


MongoDB 入门篇

1.1 NoSQL是什么?

常见数据库管理系统

常见的数据库管理系统,及其排名情况如下:

 MongoDB 入门基础知识

图 - 数据库管理系统使用情况世界排名

数据来源:https://db-engines.com/en/ranking

1.2 NoSQL是什么?


1.2.1 NoSQL简介

  NoSQL是对不同于传统的关系数据库的数据库管理系统的统称。

  NoSQL最重要的是不使用SQL作为查询语言。其数据存储可以不需要固定的表格模式,也经常会避免使用SQL的JOIN操作,一般有水平可扩展性的特征。

  NoSQL一词最早出现于1998年,是Carlo Strozzi开发的一个轻量、开源、不提供SQL功能的关系数据库。

  2009年,Last.fm的Johan Oskarsson发起了一次关于分布式开源数据库的讨论,来自Rackspace的Eric Evans再次提出了NoSQL的概念,这时的NoSQL主要指非关系型、分布式、不提供ACID的数据库设计模式。

  2009年在亚特兰大举行的"no:sql(east)"讨论会是一个里程碑,其口号是"select fun, profit from real_world where relational=false;"。因此,对NoSQL最普遍的解释是“非关联型的”,强调Key-Value Stores和文档数据库的优点,而不是单纯的反对RDBMS。

  基于2014年的收入,NoSQL市场领先企业是MarkLogic,MongoDB和Datastax。基于2015年的人气排名,最受欢迎的NoSQL数据库是MongoDB,Apache Cassandra和Redis.

1.2.2 NoSQL数据库四大家族

NoSQL中的四大家族主要是:列存储、键值、图像存储、文档存储,其类型产品主要有以下这些。

存储类型

NoSQL

键值存储

最终一致性键值存储

Cassandra、Dynamo、Riak、Hibari、Virtuoso、Voldemort

内存键值存储

Memcached、Redis、Oracle Coherence、NCache、 Hazelcast、Tuple space、Velocity

持久化键值存储

BigTable、LevelDB、Tokyo Cabinet、Tarantool、TreapDB、Tuple space

文档存储

MongoDB、CouchDB、SimpleDB、 Terrastore 、 BaseX 、Clusterpoint 、 Riak、No2DB

图存储

FlockDB、DEX、Neo4J、AllegroGraph、InfiniteGraph、OrientDB、Pregel

列存储

Hbase、Cassandra、Hypertable

1.2.3 NoSQL的优势

  高可扩展性、分布式计算、没有复杂的关系、低成本

  架构灵活、半结构化数据

1.2.4 NoSQL与RDBMS对比 

NoSQL

RDBMS

代表着不仅仅是SQL

没有声明性查询语言

没有预定义的模式

键 - 值对存储,列存储,文档存储,图形数据库

最终一致性,而非ACID属性

非结构化和不可预知的数据

CAP定理

高性能,高可用性和可伸缩性

高度组织化结构化数据

结构化查询语言(SQL) (SQL)

数据和关系都存储在单独的表中。

数据操纵语言,数据定义语言

严格的一致性

基础事务

1.3 MongoDB简介

1.3.1  MongoDB的特性

  MongoDB的3大技术特色如下所示:

 MongoDB 入门基础知识

除了上图所示的还支持

  二级索引、动态查询、全文搜索 、聚合框架、MapReduce、GridFS、地理位置索引、内存引擎 、地理分布等一系列的强大功能。

但是其也有些许的缺点,例如:

  多表关联: 仅仅支持Left Outer Join

  SQL 语句支持: 查询为主,部分支持

  多表原子事务: 不支持

  多文档原子事务:不支持

  16MB 文档大小限制,不支持中文排序 ,服务端 Javascript 性能欠佳

1.3.2关系型数据库与mongodb对比

存储方式对比

     在传统的关系型数据库中,存储方式是以表的形式存放,而在MongoDB中,以文档的形式存在

MongoDB 入门基础知识 

   数据库中的对应关系,及存储形式的说明

 MongoDB 入门基础知识

MongoDB与SQL的结构对比详解

SQL Terms/Concepts

MongoDB Terms/Concepts

database

database

table

collection

row

document or BSON document

column

field

index

index

table joins

embedded documents and linking

primary key

Specify any unique column or

column combination as

primary key.

primary key

In MongoDB, the primary key is

automatically set to the _id field.

aggregation (e.g. group by)

aggregation pipeline

See the SQL to Aggregation Mapping

Chart.

1.3.3MongoDB数据存储格式

JSON格式

  JSON 数据格式与语言无关,脱胎于 JavaScript,但目前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json。

  MongoDB 使用JSON(JavaScript ObjectNotation)文档存储记录。

  JSON数据库语句可以容易被解析。

  Web 应用大量使用,NAME-VALUE 配对

MongoDB 入门基础知识 

BSON格式

  BSON是由10gen开发的一个数据格式,目前主要用于MongoDB中,是MongoDB的数据存储格式。BSON基于JSON格式,选择JSON进行改造的原因主要是JSON的通用性及JSON的schemaless的特性。 

  二进制的JSON,JSON文档的二进制编码存储格式

  BSON有JSON没有的Date和BinData

  MongoDB中document以BSON形式存放

例如:

> db.meeting.insert({meeting:“M1 June",Date:"2018-01-06"});

1.3.4 MongoDB的优势

  •    MongoDB是开源产品
  •    On GitHub Url:https://github.com/mongodb
  •     Licensed under the AGPL,有开源的社区版本
  •    起源& 赞助by MongoDB公司,提供商业版licenses 许可

     这些优势造就了mongodb的丰富的功能:

  JSON 文档模型、动态的数据模式、二级索引强大、查询功能、自动分片、水平扩展、自动复制、高可用、文本搜索、企业级安全、聚合框架MapReduce、大文件存储GridFS

1.3.5 高可用的复制集群

  自动复制和故障切换

  多数据中心支持滚动维护无需关机支持最多50个成员

MongoDB 入门基础知识

1.3.6 水平扩展

  这种方式是目前构架上的主流形式,指的是通过增加服务器数量来对系统扩容。在这样的构架下,单台服务器的配置并不会很高,可能是配置比较低、很廉价的 PC,每台机器承载着系统的一个子集,所有机器服务器组成的集群会比单体服务器提供更强大、高效的系统容载量。

MongoDB 入门基础知识 

  这样的问题是系统构架会比单体服务器复杂,搭建、维护都要求更高的技术背景。分片集群架构如下图所示:

MongoDB 入门基础知识

1.3.7 各存储引擎的对比

 

MySQL InnoDB

MySQL NDB

Oracle

MongoDB MAPI

MongoDB WiredTiger

事务

YES

YES

ES

NO

NO

锁粒度

ROW-level

ROW-level

ROW-level

Collection-level

Document-level

Geospatial

YES

YES

YES

YES

YES

MVCC

YES

NO

YES

NO

NO

Replication

YES

YES

YES

YES

YES

外键

YES

YES(From 7.3)

YES

NO

NO

数据库集群

NO

YES

YES

YES

YES

B-TREE索引

YES

YES

YES

YES

YES

全文检索

YES

NO

YES

YES

YES

数据压缩

YES

NO

YES

NO

YES

存储限制

64TB

384EB

NO

NO

NO

表分区

YES

YES

YES

YES (分片)

YES (分片)

1.3.8 数据库功能和性能对比

  由下图可以看出MongoDB数据库的性能扩展能力及功能都较好,都能够在数据库中,站立一足之地。

MongoDB 入门基础知识 

1.3.9 MongoDB 慎用场景

慎用场景

原因

PB 数据持久存储大数据分析数据湖

Hadoop、Spark提供更多分析运算功能和工具,并行计算能力更强

MongoDB + Hadoop/Spark

搜索场景:文档有几十个字段,需要按照任意字段搜索并排序限制等

不建索引查询太慢,索引太多影响写入及更新操作

ERP、CRM或者类似复杂应用,几十上百个对象互相关联

关联支持较弱,事务较弱

需要参与远程事务,或者需要跨表,跨文档原子性更新的

MongoDB  事务支持仅限于本机的单文档事务

100% 写可用:任何时间写入不能停

MongoDB换主节点时候会有短暂的不可写设计所限

1.3.10什么时候该MongDB 

应用特征

Yes/No?

我的数据量是有亿万级或者需要不断扩容

 

需要2000-3000以上的读写每秒

 

新应用,需求会变,数据模型无法确定

 

我需要整合多个外部数据源

 

我的系统需要99.999%高可用

 

我的系统需要大量的地理位置查询

 

我的系统需要提供最小的latency

 

我要管理的主要数据对象<10

 

  在上面的表格中进行选择,但有1个yes的时候:可以考虑MongoDB;当有2个以上yes的时候:不会后悔的选择!

1.4 MongoDB的部署

  MongoDB官网:https://www.mongodb.com/

  CentOS7.X版本软件下载地址:https://www.mongodb.org/dl/linux/x86_64-rhel70

    其他版本请到进行官网下载。

1.4.1 安装前准备

  在安装之前首先确认该版本软件是否支持你的操作系统。

    更多详情查看:https://docs.mongodb.com/manual/installation/ 

Platform

3.6 Community & Enterprise

3.4 Community & Enterprise

3.2 Community & Enterprise

3.0 Community & Enterprise

RHEL/CentOS 6.2 and later

RHEL/CentOS 7.0 and later

1.4.2 环境说明

系统环境说明: 



[email protected]:/root# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core) 
[email protected]:/root# uname -a
Linux wiki 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
[email protected]:/root# /etc/init.d/iptables
-bash: /etc/init.d/iptables: No such file or directory
[email protected]:/root# geten
getenforce  getent      
[email protected]:/root# getenforce  Disable
Disabled
[email protected]:/root# more /etc/selinux/config 


# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted 

 

软件版本说明

本次使用的mongodb版本为:mongodb-linux-x86_64-3.6.2.tgz 
[email protected]:/root# cd /home/mongodb
mongodb/                        mongodb-linux-x86_64-3.6.2.tgz  


1.4.3 部署MongoDB

在root用户下操作

cat >> /etc/rc.local <<'EOF'
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
  echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
EOF
  该方法仅限与CentOS系统使用,其他系统关闭参照官方文档:         https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/
  Transparent Huge Pages (THP),通过使用更大的内存页面,可以减少具有大量内存的机器上的缓冲区(TLB)查找的开销。

  但是,数据库工作负载通常对THP表现不佳,因为它们往往具有稀疏而不是连续的内存访问模式。您应该在Linux机器上禁用THP,以确保MongoDB的最佳性能。 

 该方法仅限与CentOS系统使用,其他系统关闭参照官方文档:         https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/

  Transparent Huge Pages (THP),通过使用更大的内存页面,可以减少具有大量内存的机器上的缓冲区(TLB)查找的开销。

  但是,数据库工作负载通常对THP表现不佳,因为它们往往具有稀疏而不是连续的内存访问模式。您应该在Linux机器上禁用THP,以确保MongoDB的最佳性能。

创建用户

groupadd -g 8000 mongod
useradd  -u 8001 -g mongod  mongod
  修改用户密码
echo 123456 |passwd --stdin  mongod

创建程序目录

[email protected]:/opt/mongodb# mkdir -p /opt/mongodb/{data,logs}

下载程序

cd  /home
[email protected]:/root# wget http://downloads.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.6.2.tgz

解压程序

tar -xvf mongodb-linux-x86_64-rhel62-3.6.2.tgz

修改程序属主

chown -R mongod:mongod /opt/mongodb

  切换到mongod用户,设置用户环境变量

export MONGODB_HOME=/opt/mongodb/mongodb-linux-x86_64-3.6.2
export PATH=$MONGODB_HOME/bin:$PATH

登录MONGODB

[email protected]:/root# mongo
MongoDB shell version v3.6.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.2
Server has startup warnings: 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server. 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 

     至此,MongoDB数据库部署完成

1.4.4 管理MongoDB

  数据库的启动与关闭

启动:

mongod --config /opt/mongodb/mongodb.conf

[email protected]:/root# mongod --config /opt/mongodb/mongodb.conf
about to fork child process, waiting until server is ready for connections.
forked process: 21663
child process started successfully, parent exiting
[email protected]:/root# 

关闭:

mongod --shutdown  --config /opt/mongodb/mongodb.conf

[email protected]:/root# mongod --shutdown  --config /opt/mongodb/mongodb.conf
killing process with pid: 5677
[email protected]:/root# ps -ef|grep mongodb

   参数说明: 

参数

参数说明

--dbpath    

数据存放路径

--logpath   

日志文件路径

--logappend 

日志输出方式

--port      

启用端口号

--fork      

在后台运行

--auth      

是否需要验证权限登录(用户名和密码)

--bind_ip   

限制访问的ip

--shutdown

关闭数据库

登入数据库

[email protected]:/root# mongo
MongoDB shell version v3.6.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.2
Server has startup warnings: 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server. 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-17T10:55:56.506+0800 I CONTROL  [initandlisten] 

使用配置文件的方式管理数据库:

  普通格式配置文件:

[email protected]:/root# cd /opt/mongodb/
[email protected]:/opt/mongodb# ls
data  logs  mongodb.conf  mongodb-linux-x86_64-3.6.2  mongod.pid
[email protected]:/opt/mongodb# more mongodb.conf 
# Start MongoDB as a daemon on port 27017
port = 27017
fork = true # daemonize it !
journal = true #
#rest = true
logappend = true
#auth = true
dbpath = /opt/mongodb/data/
logpath = /opt/mongodb/logs/mongod.log
pidfilepath = /opt/mongodb/mongod.pid
[email protected]:/opt/mongodb# 

   

  YAML格式配置文件(3.X 版本官方推荐使用)

cat  mongod.conf 
systemLog:
   destination: file
   path: "/application/mongodb/log/mongod.log"
   logAppend: true
storage:
   journal:
      enabled: true
   dbPath: "/application/mongodb/data"
processManagement:
   fork: true
net:
   port: 27017

在数据库中关闭数据库的方法 

[email protected]:/opt/mongodb# mongo
MongoDB shell version v3.6.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.2
Server has startup warnings: 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server. 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] 
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-19T11:38:03.603+0800 I CONTROL  [initandlisten] 
> db
test
> use admin

switched to db admin
> db.shutdownServer()
server should be down...
2018-04-19T11:43:03.509+0800 I NETWORK  [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2018-04-19T11:43:03.510+0800 W NETWORK  [thread1] Failed to connect to 127.0.0.1:27017, in(checking socket for error after poll), reason: Connection refused
2018-04-19T11:43:03.510+0800 I NETWORK  [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) failed failed 
> exit
bye
[email protected]:/opt/mongodb# ps -ef|grep mongodb

注:

mongod进程收到SIGINT信号或者SIGTERM信号,会做一些处理

> 关闭所有打开的连接

> 将内存数据强制刷新到磁盘

> 当前的操作执行完毕

> 安全停止

  切忌kill -9

 

   数据库直接关闭,数据丢失,数据文件损失,修复数据库(成本高,有风险)

   使用kill命令关闭进程

$ kill -2 PID
  原理:-2表示向mongod进程发送SIGINT信号。

$ kill -4 PID
  原理:-4表示向mognod进程发送SIGTERM信号。
使用脚本管理mongodb服务

   注:该脚本可以直接在root用户下运行
 cat  /etc/init.d/mongod  
 #!/bin/bash
  #
  # chkconfig: 2345 80 90
  # description:mongodb
  # by clsn
  # blog_url http://blog.nmtui.com
  #################################
 MONGODIR=/application/mongodb
 MONGOD=$MONGODIR/bin/mongod
 MONGOCONF=$MONGODIR/conf/mongod.conf
 InfoFile=/tmp/start.mongo 
 . /etc/init.d/functions 
 
 status(){
   PID=`awk 'NR==2{print $NF}' $InfoFile`
   Run_Num=`ps -p $PID|wc -l`
   if [ $Run_Num -eq 2 ]; then
     echo "MongoDB is running"
   else 
     echo "MongoDB is shutdown"
     return 3
   fi
 } 
 start() {
   status &>/dev/null
   if [ $? -ne 3 ];then 
     action "启动MongoDB,服务运行中..."  /bin/false 
     exit 2
  fi
   sudo su - mongod -c "$MONGOD -f $MONGOCONF" >$InfoFile 2>/dev/null 
   if [ $? -eq 0 ];then 
     action "启动MongoDB"  /bin/true
   else
     action "启动MongoDB"  /bin/false
   fi
}
 
 
 stop() {
   sudo su - mongod -c "$MONGOD -f $MONGOCONF --shutdown"  &>/dev/null
   if [ $? -eq 0 ];then
     action "停止MongoDB"  /bin/true
   else 
     action "停止MongoDB"  /bin/false
   fi 
 }
  case "$1" in
   start)
    start
     ;;
   stop)
    stop
     ;;
  restart)
     stop
     sleep 2
     start
     ;;
   status)
     status
     ;;
   *)
      echo $"Usage: $0 {start|stop|restart|status}"
      exit 1
  esac
 

 脚本管理mongodb服务 

1.5 MongoDB的基本操作

Mongodb中关键字种类:

db(数据库实例级别)

         db本身

             db.connection 数据库下的集合信息

                 db.collection.xxx(

rs(复制集级别)

sh(分片级别)

1.5.1 查询操作

在客户端指定数据库进行连接:(默认连接本机test数据库)

[email protected]:/opt/mongodb# mongo 127.0.0.1:27017/admin
MongoDB shell version v3.6.2
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 3.6.2
Server has startup warnings: 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server. 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] 
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-04-19T13:23:42.270+0800 I CONTROL  [initandlisten] 

查看当前数据库版本

> db.version()
3.6.2

切换数据库

> use admin
switched to db admin

显示当前数据库

> db.getName()
admin
> db
admin

查询所有数据库

> show dbs;
admin   0.000GB
config  0.000GB
fang    0.311GB
local   0.000GB

查看admin数据库当前状态

> db.stats()
{
"db" : "admin",
"collections" : 1,
"views" : 0,
"objects" : 1,
"avgObjSize" : 59,
"dataSize" : 59,
"storageSize" : 16384,
"numExtents" : 0,
"indexes" : 1,
"indexSize" : 16384,
"fsUsedSize" : 5017579520,
"fsTotalSize" : 210136834048,
"ok" : 1
}

查看当前数据库的连接机器地址

> db.getMongo()
connection to 127.0.0.1:27017

1.5.2 数据管理

创建数据库

> use test2018;
switched to db test2018

说明:

创建数据库:

当use的时候,系统就会自动创建一个数据库。

如果use之后没有创建任何集合。系统就会删除这个数据库。

删除数据库

> show dbs;
admin   0.000GB
config  0.000GB
fang    0.311GB
local   0.000GB
> use test2018
switched to db test2018
> db.dropDatabase();
{ "ok" : 1 }

说明:

删除数据库:

 如果没有选择任何数据库,会删除默认的test数据库

创建集合

   方法一:

> use 2018test
switched to db 2018test
> db.createCollection('a')
{ "ok" : 1 }
> db.createCollection('b')
{ "ok" : 1 }

   查看当前数据下的所有集合

> show collections;
a
b
> db.getCollectionNames()
[ "a", "b" ]

方法二:

  当插入一个文档的时候,一个集合就会自动创建。

> use fadk;
switched to db fadk
> db.c.insert({name:'clsn'});
WriteResult({ "nInserted" : 1 })
> db.c.insert({url:'http://sina.com'});
WriteResult({ "nInserted" : 1 })

   查看创建的合集

> db.getCollectionNames()
[ "c" ]

   查看合集里的内容

> db.c.find()
{ "_id" : ObjectId("5ad82aca77d34be3a911a1cb"), "name" : "clsn" }
{ "_id" : ObjectId("5ad82adf77d34be3a911a1cc"), "url" : "http://sina.com" }

重命名集合

>  db.c.renameCollection("testccc")
{ "ok" : 1 }
> db.getCollectionNames()
[ "testccc" ]

   删除合集

> db.createCollection('bdddd')
{ "ok" : 1 }
> db.getCollectionNames()
[ "b", "bdddd", "testccc" ]
> db.b.drop()
true
> db.getCollectionNames()
[ "bdddd", "testccc" ]

   插入1w行数据

> for(i=0;i<10000;i++){ db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new Date()}); }
WriteResult({ "nInserted" : 1 })

查询集合中的查询所有记录

> db.log.find()

{ "_id" : ObjectId("5ad82c2577d34be3a911a1de"), "uid" : 17, "name" : "mongodb", "age" : 6, "date" : ISODate("2018-04-19T05:41:57.671Z") }
{ "_id" : ObjectId("5ad82c2577d34be3a911a1df"), "uid" : 18, "name" : "mongodb", "age" : 6, "date" : ISODate("2018-04-19T05:41:57.672Z") }
{ "_id" : ObjectId("5ad82c2577d34be3a911a1e0"), "uid" : 19, "name" : "mongodb", "age" : 6, "date" : ISODate("2018-04-19T05:41:57.673Z") }
Type "it" for more

注:默认每页显示20条记录,当显示不下的的情况下,可以用it迭代命令查询下一页数据。



DBQuery.shellBatchSize=50;    # 每页显示50条记录
50 
db.log.findOne()            # 查看第1条记录
db.log.count()              # 查询总的记录数
db.log.find({uid:1000});    # 查询UUID为1000的数据

删除集合中的记录数

>  db.log.distinct("name")      #  查询去掉当前集合中某列的重复数据
[ "mongodb" ]
> db.log.remove({})             #  删除集合中所有记录
WriteResult({ "nRemoved" : 10000 })  
> db.log.distinct("name")
[ ]

查看集合存储信息

> db.log.stats()          # 查看数据状态
> db.log.dataSize()       # 集合中数据的原始大小
> db.log.totalIndexSize() # 集合中索引数据的原始大小
> db.log.totalSize()      # 集合中索引+数据压缩存储之后的大小
> db.log.storageSize()    # 集合中数据压缩存储的大小

pretty()使用

> db.log.find({uid:1000}).pretty()
{
    "_id" : ObjectId("5a4c5c0bdf067ab57602f7c2"),
    "uid" : 1000,
    "name" : "mongodb",
    "age" : 6,
    "date" : ISODate("2018-01-03T04:28:59.343Z")
}

1.6 MongoDB中用户管理

  MongoDB数据库默认是没有用户名及密码的,即无权限访问限制。为了方便数据库的管理和安全,需创建数据库用户。

1.6.1 用户的权限

 用户权限设置总结

Ø  MongoDB是没有默认管理员账号,所以要先添加管理员账号,再开启权限认证。

Ø  切换到admin数据库,添加的账号才是管理员账号。

Ø  用户只能在用户所在数据库登录,包括管理员账号。

Ø  管理员可以管理所有数据库,但是不能直接管理其他数据库,要先在admin数据库认证后才可以。

Built-In Roles(内置角色):

   1. 数据库用户角色:read、readWrite;

   2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;

   3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;

   4. 备份恢复角色:backup、restore;

   5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase

   6. 超级用户角色:root 

   // 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)

   7. 内部角色:__system

MongoDB内建角色包括以下几类

1)    数据库用户角色

read:允许用户读取指定数据库

readWrite:允许用户读写指定数据库

2)    数据库管理员角色

dbAdmin:允许用户进行索引创建、删除,查看统计或访问system.profile,但没有角色和用户管理的权限

userAdmin:提供了在当前数据库中创建和修改角色和用户的能力

dbOwner提供对数据库执行任何管理操作的能力。这个角色组合了readWritedbAdminuserAdmin角色授予的特权。

3)    集群管理角色

clusterAdmin 提供最强大的集群管理访问。组合clusterManagerclusterMonitorhostManager角色的能力。还提供了dropDatabase操作

clusterManager 在集群上提供管理和监视操作。可以访问配置和本地数据库,这些数据库分别用于分片和复制

clusterMonitor 提供对监控工具的只读访问,例如MongoDB云管理器和Ops管理器监控代理。

hostManager 提供监视和管理服务器的能力。

4)    备份恢复角色

backup 提供备份数据所需的能力,使用MongoDB云管理器备份代理、Ops管理器备份代理或使用mongodump

restore 提供使用mongorestore恢复数据所需的能力

5)    所有数据库角色

readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限

readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限

userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限

dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。

6)    超级用户角色

root:提供对readWriteAnyDatabasedbAdminAnyDatabaseuserAdminAnyDatabaseclusterAdminrestorebackup的所有资源的访问

7)    内部角色

__system : 提供对数据库中任何对象的任何操作的特权

   更多关于用户权限的说明参照:https://docs.mongodb.com/manual/core/security-built-in-roles/

用户创建语法  

{user: "<name>", pwd: "<cleartext password>", customData: { <any information> }, roles: [ { role: "<role>", db: "<database>" } | "<role>", ... ] }

语法说明:

user字段:用户的名字;

pwd字段:用户的密码;

cusomData字段:为任意内容,例如可以为用户全名介绍;

roles字段:指定用户的角色,可以用一个空数组给新用户设定空角色;

 

roles 字段:可以指定内置角色和用户定义的角色。

1.6.2 创建管理员用户

进入管理数据库

> use admin

创建管理用户,root权限

db.createUser(  {    user: "root",    pwd: "root",    roles: [ { role: "root", db: "admin" } ]  })    

注意:

     创建管理员角色用户的时候,必须到admin下创建。

 

     删除的时候也要到相应的库下操作。

查看创建完用户后的collections;

 > show tables; system.users  # 用户存放位置system.version

查看创建的管理员用户

    > show users    {        "_id" : "admin.root",        "user" : "root",        "db" : "admin",        "roles" : [            {                "role" : "root",                "db" : "admin"            }        ]    }

验证用户是否能用

> db.auth("root","root")1  # 返回 1 即为成功

用户创建完成后在配置文件中开启用户验证

cat >>/application/mongodb/conf/mongod.conf<<-'EOF'security:  authorization: enabledEOF

重启服务

/etc/init.d/mongod  restart

  登陆测试,注意登陆时选择admin数据库

    注意:用户在哪个数据库下创建的,最后加上什么库。

方法一:命令行中进行登陆

[[email protected] ~]$ mongo -uroot -proot admin MongoDB shell version: 3.2.8connecting to: admin> 

方法二:在数据库中进行登陆验证:

[[email protected] ~]$ mongo MongoDB shell version: 3.2.8connecting to: test> use adminswitched to db admin> db.auth("root","root")1> show tables;system.userssystem.version

1.6.3 按生产需求创建应用用户

创建对某库的只读用户

   在test库创建只读用户test

use testdb.createUser(  {    user: "test",    pwd: "test",    roles: [ { role: "read", db: "test" } ]  })

   测试用户是否创建成功

db.auth("test","test")show  users;

登录test用户,并测试是否只读

show collections;db.createCollection('b')

创建某库的读写用户

  创建test1用户,权限为读写

db.createUser(  {    user: "test1",    pwd: "test1",    roles: [ { role: "readWrite", db: "test" } ]  })

   查看并测试用户

show users;db.auth("test1","test1")

创建对多库不同权限的用户

   创建对app为读写权限,对test库为只读权限的用户

use appdb.createUser(  {    user: "app",    pwd: "app",roles: [ { role: "readWrite", db: "app" },         { role: "read", db: "test" } ]  })

查看并测试用户

show usersdb.auth("app","app")

删除用户

   删除app用户:先登录到admin数据库

mongo -uroot –proot 127.0.0.1/admin

   进入app库删除app用户

use appdb.dropUser("app")

1.6.4 自定义数据库

创建app数据库的管理员:先登录到admin数据库

use appdb.createUser({user: "admin",pwd: "admin",roles: [ { role: "dbAdmin", db: "app" } ]})

创建app数据库读写权限的用户并具有clusterAdmin权限:

use appdb.createUser({user: "app04",pwd: "app04",roles: [ { role: "readWrite", db: "app" },{ role: "clusterAdmin", db: "admin" }]})
1.6.5 创建具体权限的用户例子

use admin 

db.createUser({user:'superadmin',pwd:'123456',roles:[{role:'root', db:'admin'}]})     ---创建超级管理员用户 

db.createUser({user:'useradmin',pwd:'123456',roles:[{role:'userAdminAnyDatabase', db:'admin'}]})     ---创建用户管理员账户(能查询其他库集合,但不能查询集合内容) 

db.createUser({user:'admin',pwd:'123456',roles:[{role:'readWriteAnyDatabase', db:'admin'}]})     ---创建访问任意库读写的账户 

db.createUser({user:'user1',pwd:'user1',roles:[{role:'readWrite',db:'test'}]})     ---创建只对test库有读写权限的用户 

db.createUser({user:"bkuser2",pwd:"Bkuser2",roles:[{role:"backup",db:"admin"}]})     ---创建用于备份时的用户,如若是恢复权限,则将backup换为restore即可 

注:新建backup账户时,roles里面的db必须是admin,要不然会报错。

1.6.5.1      验证新建用户

用户在哪个库新建授权,则需要在哪个库进行auth验证,注意一点,帐号是跟着库走的,所以在指定库里授权,必须也在指定库里验证(auth)   

>db    ---查看当前所在库 

test 

>db.createUser({user:'test1',pwd:'test1',roles:[{role:'readWrite',db:'test'},{role:'read',db:'Johnny'})}) 

>use Johnny 

Johnny 

>db.auth('test1','test1') 

Error:Authentication failed. 

0         ---表示auth验证失败  

>use test 

>db.auth('test1','test1') 

1          ---表示验证成功 

所以说明一点,用户在哪个库创建,就要在哪个库auth认证,并在mongo登录时也要先连接认证库

1.6.5.2   查询用户

查询用户:

     查询实例中所有的用户信息

>use admin

>db.system.users.find().pretty()          ---将所有用户信息查询出来

显示某一库下的所有用户

>use test

>show users                              ---显示在此库授权的用户信

查询指定用户的相关信息

db.getUser("jianlong")     ---需要在用户所在库才能执行此命令并获得信息,查询到的信息和“show user”一样,只是可以指定用户罢了 

1.6.5.3 修改用户

语法结构:

db.updateUser( 

 "<username>", 

 { 

   customData : { <any information> }, 

   roles : [ 

              { role: "<role>",db: "<database>" } | "<role>", 

              ... 

           ], 

   pwd: "<cleartext password>" 

   }, 

   writeConcern: { <write concern> }) 

1.6.5.4     修改用户权限

可以通过此命令修改用户的权限,但使用此命令修改权限时,则会覆盖原先的所有权限

例:

 db.updateUser("root",{roles:[{role:"readWriteAnyDatabase",db:"admin"}]})             

     在原来权限上新增权限:

> use Johnny 

>db.grantRolesToUser("jianlong",[{role:'readWrite',db:'test'}])     ---不会覆盖原权限信息,只新增权限 

> show users; 

>use tt 

>db.grantRolesToUser("jianlong",[{role:'read',db:'tt'}])       

---不能在用户非授权库进行用户的权限添加,否则会报错,即表现出账户跟着库走的特点 

 

1.6.5.5     修改用户密码

     使用db.changeUserPassword(“username","newPasswd")

> use tt

switched to db tt

>db.changeUserPassword("tuser","123456")          ---注意要在账户所在授权库执行此命令

1.6.5.6    删除用户

>db.dropUser("test1")

1.6.5.7    用户自定义角色Role

db.createRole( 

 role: "<name>",                    ---role名字 

 privileges: [ 

    {resource: { <resource> }, actions: [ "<action>", ... ]},          ---配置具体对象的权限,比如对某集合的find,insert等权限 

   ... 

 ], 

 roles: [ 

    {role: "<role>", db: "<database>" } |"<role>",              ---继承其他角色权限,可以数组为空 

     ... 

      ]  }  ) 

查看角色的具体privilege(权限):

>db.getRole("SenderHis_Read",{showPrivileges:true})

另一参数:show BuiltinRoles

注:Resource具有 database collection cluster anyResource4种类型

Resource具有 database collection cluster anyResource4种类型



1.7 SQL与MongoDB语言对比

SQL语言与CRUD语言对照 

SQL Schema Statements

MongoDB Schema Statements

CREATE TABLE users (

id MEDIUMINT NOT NULL

AUTO_INCREMENT,

user_id Varchar(30),

age Number,

status char(1),

PRIMARY KEY (id)

)

Implicitly created on first insert() operation. The primary

key _idis automatically added if _id field is not specified.

db.users.insert( {

user_id: "abc123",

age: 55,

status: "A"

} )

However, you can also explicitly create a collection:

db.createCollection("users")

ALTER TABLE users

ADD join_date DATETIME

在Collection 级没有数据结构概念。然而在 document级,可以通过$set在

update操作添加列到文档中。

db.users.update(

{ },

{ $set: { join_date: new Date() } },

{ multi: true }

)

ALTER TABLE users

DROP COLUMN join_date

在Collection 级没有数据结构概念。然而在 document级,可以通过$unset

在update操作从文档中删除列。

db.users.update(

{ },

{ $unset: { join_date: "" } },

{ multi: true }

)

CREATE INDEX idx_user_id_asc

ON users(user_id)

db.users.createIndex( { user_id: 1 } )

CREATE INDEX

idx_user_id_asc_age_desc

ON users(user_id, age DESC)

db.users.createIndex( { user_id: 1, age: -1 } )

DROP TABLE users

db.users.drop()

插入/删除/更新 语句对比

SQL  Statements

MongoDB  Statements

INSERT INTO

users(user_id,

age

status)

VALUES ("bcd001",

45,

"A")

db.users.insert(

{ user_id: "bcd001", age:

45, status: "A" }

)

DELETE FROM users

WHERE status = "D"

db.users.remove( { status: "D" } )

DELETE FROM users

db.users.remove({})

UPDATE users

SET status = "C"

WHERE age > 25

db.users.update(

{ age: { $gt: 25 } },

{ $set: { status: "C" } },

{ multi: true }

)

UPDATE users

SET age = age + 3

WHERE status = "A"

db.users.update(

{ status: "A" } ,

{ $inc: { age: 3 } },

{ multi: true }

)

查询类操作对比 

SQL SELECT Statements

MongoDB find() Statements

SELECT *

FROM users

db.users.find()

SELECT id,

user_id,

status

FROM users

db.users.find(

{ },

{ user_id: 1, status: 1, _id: 0 }

)

SELECT user_id, status

FROM users

db.users.find(

{ },

{ user_id: 1, status: 1 }

)

SELECT *

FROM users

WHERE status = "A"

db.users.find(

{ status: "A" }

)

SELECT user_id, status

FROM users

WHERE status = "A"

db.users.find(

{ status: "A" },

{ user_id: 1, status: 1, _id: 0 }

)

1.8 错误解决

  在登陆数据库的时候,发现会由描述文件相关的报错。
 ** WARNING: soft rlimits too low. rlimits set to 19193 processes, 65535 files. Number of processes should be at least 32767.5 : 0.5 times number of files.

解决办法:

cat >> /etc/security/limits.conf <<EOFmongod   soft     nofile     32767.5mongod   soft     nproc      32767.5EOF

   修改后,重启服务器,即可解决该问题。

1.9 参考文献