以前用MySQL数据库,整天都是写大堆大堆的SQL语句,要记住这些SQL关键字都要花好几天时间,写的蛋都爆了,当接触到MongoDB的时候,发现不用写SQL,瞬间觉得高大上,瞬间产生了学习使用它的冲动。

1.MongoDB简介

MongoDB是一种强大,灵活,可扩展的数据存储方式。它扩展了关系型数据库的众多有用功能,如辅助索引,范围查询和排序。MongoDB的功能非常丰富,比如内置的对MapReduce式聚合的支持,以及对地理空间索引的支持。还有很多很多的特点。。。

对于入门级别的人来说,上面说的这些都是浮云,我现在体会不到它的容量,也体会不到它的横向扩展,更体会不到它的速率,这些都是当我们玩到一定的境界才会关心的问题。我单纯觉得它的好处就是非常容易上手,提供了一系列的API,不用写SQL语句。至于它和关系型数据库有什么区别,有哪些优点或者哪些缺点需要怎样改进都是以后的事了。

2.MongoDB的安装

mongodb的官网就有下载,根据系统windows还是linux还是别的下载32位还是64位的,然后解压安装。我是在Linux上安装的,刚开始是在自己的虚拟机上通过root用yum安装的,后来是通过secureCRT连接别的服务器在自己的用户上安装学习的,这样就可以玩自己的mongodb不至于弄挂服务器上面的,但是这样不能通过yum了,源码安装貌似又有很多的软件依赖,所以就在官网上下载了一个linux版的,然后通过SFTP上传到服务器上解压后直接使用。

3.MongoDB的管理

解压完之后进入bin目录,里面都是一些可执行文件,mongo,mongod,mongodump,mongoexport等,后面再说它们的作用吧。

1).启动和停止MongoDB

通过执行mongod来启动MongoDB服务器,mongod有很多的配置启动选项的,可以通过mongod --help来查看,其中有一些主要的选项:

--dbpath:指定数据目录,默认是/data/db/。每个mongod进程都需要独立的目录,启动mongod时就会在数据目录中创建mongod.lock文件,防止其他mongod进程使用该数据目录。

--port:指定服务器监听的端口,默认是27017。

--fork:以守护进程的方式运行MongoDB。

--logpath:指定日志输出路径,如果不指定则会在终端输出。每次启动都会覆盖原来的日志,如果不想覆盖就要用--logappend选项。

--config:指定配置文件,加载命令行未指定的各种选项。我们可以讲我们需要用到的选项写在某个文件中,然后通过该选项来指定这个文件就不必每次启动mongod时都要写。

比如我的配置文件mongodb.conf有如下配置:

1
2
3
4
port = 9352
#fork = true              #为注释
#logpath = mongodb.log
dbpath = data/db 

执行mongod启动MongoDB服务器指定配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[tp0352@server0 bin]$ ./mongod --config mongodb.conf
2014-06-05T17:11:13.118+0800 [initandlisten] MongoDB starting : pid=18077 port=9352 dbpath=data/db 64-bit host=server0.169
2014-06-05T17:11:13.119+0800 [initandlisten] db version v2.6.1
2014-06-05T17:11:13.119+0800 [initandlisten] git version: 4b95b086d2374bdcfcdf2249272fb552c9c726e8
2014-06-05T17:11:13.119+0800 [initandlisten] build info: Linux build14.nj1.10gen.cc 2.6.32-431.3.1.el6.x86_64 #1 SMP Fri Jan 3 21:39:27 UTC 2014 x86_64 BOOST_LIB_VERSION=1_49
2014-06-05T17:11:13.119+0800 [initandlisten] allocator: tcmalloc
2014-06-05T17:11:13.119+0800 [initandlisten] options: { config: "mongodb.conf", net: { port: 9352 }, storage: { dbPath: "data/db" } }
2014-06-05T17:11:13.246+0800 [initandlisten] journal dir=data/db/journal
2014-06-05T17:11:13.246+0800 [initandlisten] recover : no journal files present, no recovery needed
2014-06-05T17:11:15.333+0800 [initandlisten] preallocateIsFaster=true 20.74
2014-06-05T17:11:17.692+0800 [initandlisten] preallocateIsFaster=true 13.72
2014-06-05T17:11:20.858+0800 [initandlisten] preallocateIsFaster=true 23.86
2014-06-05T17:11:20.858+0800 [initandlisten] preallocateIsFaster check took 7.612 secs
2014-06-05T17:11:20.858+0800 [initandlisten] preallocating a journal file data/db/journal/prealloc.0
2014-06-05T17:11:23.121+0800 [initandlisten]            File Preallocator Progress: 492830720/1073741824        45%
2014-06-05T17:11:26.424+0800 [initandlisten]            File Preallocator Progress: 681574400/1073741824        63%
2014-06-05T17:11:29.004+0800 [initandlisten]            File Preallocator Progress: 964689920/1073741824        89%
2014-06-05T17:11:34.558+0800 [initandlisten] preallocating a journal file data/db/journal/prealloc.1
2014-06-05T17:11:37.089+0800 [initandlisten]            File Preallocator Progress: 524288000/1073741824        48%
2014-06-05T17:11:40.090+0800 [initandlisten]            File Preallocator Progress: 807403520/1073741824        75%
2014-06-05T17:11:43.063+0800 [initandlisten]            File Preallocator Progress: 1017118720/1073741824       94%
2014-06-05T17:11:48.020+0800 [initandlisten] preallocating a journal file data/db/journal/prealloc.2
2014-06-05T17:11:51.040+0800 [initandlisten]            File Preallocator Progress: 576716800/1073741824        53%
2014-06-05T17:11:54.039+0800 [initandlisten]            File Preallocator Progress: 807403520/1073741824        75%
2014-06-05T17:11:57.026+0800 [initandlisten]            File Preallocator Progress: 1069547520/1073741824       99%
2014-06-05T17:12:01.985+0800 [FileAllocator] allocating new datafile data/db/local.ns, filling with zeroes...
2014-06-05T17:12:01.985+0800 [FileAllocator] creating directory data/db/_tmp
2014-06-05T17:12:02.285+0800 [FileAllocator] done allocating datafile data/db/local.ns, size: 16MB,  took 0.167 secs
2014-06-05T17:12:02.315+0800 [FileAllocator] allocating new datafile data/db/local.0, filling with zeroes...
2014-06-05T17:12:02.413+0800 [FileAllocator] done allocating datafile data/db/local.0, size: 64MB,  took 0.097 secs
2014-06-05T17:12:02.434+0800 [initandlisten] build index on: local.startup_log properties: { v: 1, key: { _id: 1 }, name: "_id_", ns: "local.startup_log" }
2014-06-05T17:12:02.434+0800 [initandlisten]     added index to empty collection
2014-06-05T17:12:02.456+0800 [initandlisten] command local.$cmd command: create { create: "startup_log", size: 10485760, capped: true } ntoreturn:1 keyUpdates:0 numYields:0  reslen:37 494ms
2014-06-05T17:12:02.457+0800 [initandlisten] waiting for connections on port 9352

启动MongoDB服务器成功,监听端口9352,等待客户端来连接。如果指定日志文件,这些日志就会被输出到指定的日志文件。如果设置为守护进程,就会创建一个子进程,当MongoDB服务器启动完成后父进程就会退出。

让MongoDB稳妥的停下来很重要,因为可能有的数据还在缓存没写入磁盘,稳妥停止是先让数据写进磁盘然后再结束MongoDB进程。可以直接用ctrl+c来停止MongoDB服务器,也可以通过客户端来,mongo是一个javascript shell,启动它的时候会自动连接MongoDB服务器,所以mongo也是一个MongoDB客户端,它可以运行任何javascript程序,也可以操作数据库。下面来看一下mongo停止MongoDB服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[tp0352@server0 bin]$ ./mongo --port 9352
MongoDB shell version: 2.6.1
connecting to: 127.0.0.1:9352/test
> show dbs
admin  (empty)
local  0.078GB
test   (empty)
> use admin
switched to db admin
> db.shutdownServer()
2014-06-05T17:21:59.263+0800 DBClientCursor::init call() failed
server should be down...
2014-06-05T17:21:59.265+0800 trying reconnect to 127.0.0.1:9352 (127.0.0.1) failed
2014-06-05T17:21:59.266+0800 warning: Failed to connect to 127.0.0.1:9352, reason: errno:111 Connection refused
2014-06-05T17:21:59.266+0800 reconnect 127.0.0.1:9352 (127.0.0.1) failed failed couldn't connect to server 127.0.0.1:9352 (127.0.0.1), connection attempt failed
> exit
bye

从上面可以看出,我们连接到了本地9352端口test数据库,admin就是一个root数据库,这个数据库是用来管理整个MongoDB的,不是任何人都可以停止MongoDB服务器的,所以要使用admin来执行shutdownServer()来停止。

2).安全和认证

上面通过mongo这个客户端来连接MongoDB服务器,没有任何的安全认证,也就是说任何人都可以连上去,当然可以在一个可信环境中运行它,保证只有可信的机器才能访问它,也可以对单个连接的认证。每个MongoDB的数据库都可以有许多用户,如果开启了安全性检查,则只有数据库认证用户才能执行相关的操作。admin的用户可以对任何数据库进行读写操作,其他数据库的用户只能执行相关权限的操作。

开启安全检查前,先创建几个用户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> use admin
switched to db admin
> db.addUser("tp", "12345")
WARNING: The 'addUser' shell helper is DEPRECATED. Please use 'createUser' instead
Successfully added user: { "user" : "tp", "roles" : [ "root" ] }
> use test
switched to db test
> db.addUser("test1", "12345", true)
WARNING: The 'addUser' shell helper is DEPRECATED. Please use 'createUser' instead
Successfully added user: { "user" : "test1", "roles" : [ "read" ] }
> db.addUser("test2", "12345")
WARNING: The 'addUser' shell helper is DEPRECATED. Please use 'createUser' instead
Successfully added user: { "user" : "test2", "roles" : [ "dbOwner" ] }
> use admin
switched to db admin
> show collections
system.indexes
system.users
system.version
> db.system.users.find()
{ "_id" : "admin.tp", "user" : "tp", "db" : "admin", "credentials" : { "MONGODB-CR" : "e4aafd1c8d19d9e490192fe5bf43ffe0" }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "test.test1", "user" : "test1", "db" : "test", "credentials" : { "MONGODB-CR" : "2da1438b5a04dd46cfdf97c40a3c6d71" }, "roles" : [ { "role" : "read", "db" : "test" } ] }
{ "_id" : "test.test2", "user" : "test2", "db" : "test", "credentials" : { "MONGODB-CR" : "4accbd2cb1dce25ed8b3b162103b0b87" }, "roles" : [ { "role" : "dbOwner", "db" : "test" } ] }

在admin中添加了一个用户tp,在test数据库中添加了两个用户test1和test2,addUser()有三个参数,第一个是用户名,第二个是密码,第三个是只读状态,设置true为只读。从用户集合system.users可以看出,tp是admin数据库中的超级用户,有root权限,test1只有read权限,test2是dbOwner,可以读也可以写。addUser还能修改用户密码和只读状态。下面重启MongoDB服务器,添加--auth命令选项来开启安全检查,然后再通过mongo来连接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
> show dbs
2014-06-05T17:59:57.519+0800 listDatabases failed:{
        "ok" : 0,
        "errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }",
        "code" : 13
} at src/mongo/shell/mongo.js:47
> use test
switched to db test
> db.auth("test1", "12345")
1
> show collections
people
system.indexes
> db.people.find()
{ "_id" : ObjectId("53903f7af73bb0df22f8e4a6"), "name" : "Mary", "age" : 10 }
> db.people.insert({"name" : "join", "age" : 20})
WriteResult({
        "writeError" : {
                "code" : 13,
                "errmsg" : "not authorized on test to execute command { insert: \"people\", documents: [ { _id: ObjectId('53903fd6959e902814f56d8c'), name: \"join\", age: 20.0 } ], ordered: true }"
        }
})
> db.auth("test2", "12345")
1
> db.people.find()
{ "_id" : ObjectId("53903f7af73bb0df22f8e4a6"), "name" : "Mary", "age" : 10 }
> db.people.insert({"name" : "join", "age" : 20})
WriteResult({ "nInserted" : 1 })
> use admin
switched to db admin
> db.auth("tp", "12345")
1
> show dbs
admin  0.078GB
local  0.078GB
test   0.078GB

连接到MongoDB服务器后没有进行用户认证,所以什么都不能干,当使用test数据库并进行用户认证后,就可以查看test库中的集合,因为test1只能读不能写,所以find可以成功而insert失败,test2既能读也能写,使用admin数据库进行用户认证后就可以查看所有的数据库列表。其实这样的认证用途不是很大,只是一种方式而已,最安全的方式还是限制访问。

3).数据备份

①.数据文件备份

最简单的备份就是数据文件的备份,就是直接赋值data/db这个目录,因为我们前面已经指定了数据目录就是data/db,那么MongoDB多有的数据都在这里,但是有个问题就是最新的数据还在缓存中,没用同步到磁盘,可以先停止shutdownServer()再备份。但是这样会影响MongoDB正常的工作。

②.mongodump和mongorestore

bin中还有mongodump和mongorestore两个可执行文件,这个是对MongoDB的某个数据库进行备份,可以在MongoDB正在运行时进行备份,比如备份test数据库,然后将备份的数据库文件再倒入别的MongoDB服务器上。这种备份的方式备份的不是最新数据,只是已经写入MongoDB中的数据,可能还有的数据在缓存中没有写入,那么这部分数据就是备份不到的。mongodump和mongorestore也可以通过--help查询所有选项。

1
2
3
4
5
6
7
8
[tp0352@server0 bin]$ ./mongodump --port 9352 -d test -o test_data
connected to: 127.0.0.1
2014-06-05T19:00:03.381+0800 DATABASE: test      to     test_data/test
2014-06-05T19:00:03.411+0800    test.system.indexes to test_data/test/system.indexes.bson
2014-06-05T19:00:03.426+0800             1 documents
2014-06-05T19:00:03.426+0800    test.test to test_data/test/test.bson
2014-06-05T19:00:03.463+0800             1 documents
2014-06-05T19:00:03.464+0800    Metadata for test.test to test_data/test/test.metadata.json

-d是指定数据库,-o是输出备份文件,上面将test数据库备份为test_data文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[tp0352@server0 bin]$ ./mongorestore --port 9352 -d temple --drop test_data/test/
connected to: 127.0.0.1:9352
2014-06-05T19:05:53.454+0800 test_data/test/people.bson
2014-06-05T19:05:53.454+0800    going into namespace [temple.people]
2014-06-05T19:05:53.454+0800     dropping
2 objects found
2014-06-05T19:05:53.454+0800    Creating index: { key: { _id: 1 }, name: "_id_", ns: "temple.people" }
[tp0352@server0 bin]$ ./mongo --port 9352
MongoDB shell version: 2.6.1
connecting to: 127.0.0.1:9352/test
> show dbs
admin   0.078GB
local   0.078GB
temple  0.078GB
test    0.078GB

这里将上面备份出来的test数据库现在重新导入到temple数据库,--drop代表如果有了temple数据库则将其中的所有集合删除,不指定就会和原来temple中的集合合并。

③.mongoexport和mongoimport

上面讲到mongodump和mongorestore是备份某个数据库的,那么mongoexport和mongoimport就是备份某个数据库中的某个表,同样可以通过--help来查看所有的选项,当然mongoexport也是可以不统计的备份,但是却不一定是最新数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[tp0352@server0 bin]$ ./mongoexport --port 9352 -d test -c people -o prson
connected to: 127.0.0.1:9352
exported 2 records
[tp0352@server0 bin]$ cat prson
{ "_id" : { "$oid" : "53903f7af73bb0df22f8e4a6" }, "name" : "Mary", "age" : 10 }
{ "_id" : { "$oid" : "53903ff6959e902814f56d8d" }, "name" : "join", "age" : 20 }
[tp0352@server0 bin]$ ./mongoimport --port 9352 -d temple -c user prson
connected to: 127.0.0.1:9352
2014-06-05T19:14:00.555+0800 imported 2 objects
[tp0352@server0 bin]$ ./mongo --port 9352
MongoDB shell version: 2.6.1
connecting to: 127.0.0.1:9352/test
> use temple
switched to db temple
> show collections
system.indexes
user
> db.user.find()
{ "_id" : ObjectId("53903f7af73bb0df22f8e4a6"), "name" : "Mary", "age" : 10 }
{ "_id" : ObjectId("53903ff6959e902814f56d8d"), "name" : "join", "age" : 20 }

-c表示collection集合,上面将test库中的people集合备份出来为prson文件,然后再导入到temple库中的user集合。

④.fsync和锁

mongodump和mongoexport对都可以不停MongoDB服务器来进行备份,但是却失去了获取实时数据的能力,而fsync命令也能在不停MongoDB的情况下备份实时数据,它的实现其实就是上锁,阻止对数据库的写入操作,然后将缓冲区的数据写入磁盘,备份后再解锁。在这个期间,任何对数据库的写入操作都会阻塞,直到锁被释放。

1
2
3
4
5
6
7
8
9
10
11
> db.runCommand({"fsync" : 1, "lock" : 1})
{
        "info" : "now locked against writes, use db.fsyncUnlock() to unlock",
        "seeAlso" : "http://dochub.mongodb.org/core/fsynccommand",
        "ok" : 1
}
>
>在这之间进行备份,执行任何insert操作都会阻塞
>
> db.fsyncUnlock()
{ "ok" : 1, "info" : "unlock completed" }

我觉得其实实时也是相对的,将数据库锁住不让写,那么最新的数据还是没备份到。

MongoDB入门学习(一):MongoDB的安装和管理的更多相关文章

  1. MongoDB入门学习(一)—— 安装和启动

    最近由于工作需要,开始学习MongoDB数据库了.第一篇博文就从这里开始吧,以此记录下学习中的点点滴滴,为自己加油呢! (一) MongoDB简介 网上搜搜了一下:(来源:http://www.run ...

  2. MongoDB入门学习笔记之简介与安装配置

    一.MongoDB简介 1.文档数据库 MongoDB是一款开源的文档型非关系数据库,具有高性能.高可靠性和自动扩展等特点.MongoDB中的每一条记录是一个文档,其数据存储结构为键/值对,类似JSO ...

  3. MongoDB快速入门学习笔记1 windows安装MongoDB

    1.安装MongoDB 从MongoDB官网上下载MongoDB,我下载的版本是64位的3.2.6.下载完以后直接安装,我的安装目录是D:\work\MongoDB. 2.配置MongoDB的环境变量 ...

  4. MongoDB入门学习(二):MongoDB的基本概念和数据类型

    上一篇讲了MongoDB的安装和管理,当中涉及到了一些概念,数据结构另一些API的调用,不知道的没关系,事实上非常easy,这篇会简介一下. 1.文档 文档是MongoDB的核心概念.多个键值对有序的 ...

  5. MongoDB入门三:MongoDB shell

    MongoDB shell MongDB shell是一个功能完备的Javascript解释器,可以运行Javascript程序.也可以用于连接MongoDB服务器,执行脚本,对数据库进行操作.类似于 ...

  6. Grunt入门学习之(1) -- 环境安装

    Grunt入门学习(1) - 环境安装 这周根据项目需要,在项目的基础上分模块开发了一个小的项目板块,但是在规范组织每个模块的代码和其依赖性时比较麻烦,需要一个项目板块的构建工具.各个模块都包括其对应 ...

  7. NOSQL Mongo入门学习笔记 - MongoDB的安装(一)

    手上的工作不是很忙,所以来学习学习很久就像接触的MongoDb,无奈前段时间工作时间都比较多.记录在这里供以后参考 环境: Centos 7 64位 开始: 1. 在官网下载Mongo : wget  ...

  8. mongodb入门学习小记

    Mongodb 简单入门(个人学习小记) 1.安装并注册成服务:(示例) E:\DevTools\mongodb3.2.6\bin>mongod.exe --bind_ip 127.0.0.1 ...

  9. mongodb的学习-3-在Mac上的安装配置

    1.使用homebrew安装: brew install mongodb 查看安装好的版本: mongo --version MongoDB shell version v3.6.4 git vers ...

随机推荐

  1. 关于EsayUI中datagrid重复提交后台查询数据的问题

    直接上代码: <table id="XXXX" style="width:100%;height:100%;" class="easyui-da ...

  2. 业余草双因素认证(2FA)教程

    所谓认证(authentication)就是确认用户的身份,是网站登录必不可少的步骤.密码是最常见的认证方法,但是不安全,容易泄露和冒充.越来越多的地方,要求启用双因素认证(Two-factor au ...

  3. Leetcode题解(一)

    1.Two Sum 题目 此题第一解题思路,就是最常见的方法,两个指针嵌套遍历数组,依次判断当前指针所指向的值是否满足条件.代码如下; class Solution { public: vector& ...

  4. Solitaire

    Solitaire Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  5. arrow functions 箭头函数

    ES6里新增加的,与普通方法不同的地方 1.this 的对象在定义函数的时候确定了,而不是在使用的时候才决定 2.不可以使用 new  ,也就不能当构造函数 3.this 的值一旦确定无法修改     ...

  6. RPC 调用简述

    首先了解什么叫RPC,为什么要RPC,RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网 ...

  7. HTTP中的Range: bytes=0-

    HTTP中的Range就是分段请求字节数,也是大家经常说的断点续传.Range头域可以请求实体的一个或者多个子范围,Range的值为0表示第一个字节,也就是Range计算字节数是从0开始的 表示第二个 ...

  8. scrapy爬虫框架之理解篇(个人理解)

    提问: 为什么使用scrapy框架来写爬虫 ?            在python爬虫中:requests  +  selenium  可以解决目前90%的爬虫需求,难道scrapy 是解决剩下的1 ...

  9. 基础进阶(一)之HashMap实现原理分析

    HashMap实现原理分析 1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二 ...

  10. Python的classmethod和staticmethod区别

    静态方法(staticmethod) 类方法(classmethod) 静态方法和类方法都可以通过类名.方法名或者实例.方法访问. #-*- coding:utf8 -*- class A(objec ...