MongoDB07-数据库管理

  • 因为MongoDB是一个非关系数据库系统,所以许多关系数据库管理员需要执行的操作,MongoDB并不需要执行。例如,不需要在MongoDB服务器上创建数据库、集合或字段,因为在访问它们时动态创建这些元素。
  • 不需要预定义所有元素,例如文档中的字段。管理员和开发者只需要偶尔从数据库中清除未使用的数据元素即可,尤其是在项目的开发阶段,开发者在最后确定解决方案之前可能尝试多种方案。MongoDB也鼓励了这种探索性的开发模式,不过,也可能导致数据库产生混乱。
  • MongoDB中的所有对象和元素名称都区分大小写。

1、MongoDB控制台:mongo

  • MongoDB管理员主要使用的工具是MongoDB控制台:mongo。
  • mongo是一个基于JavaScript的命令行控制台工具,它类似于主流关系数据库所提供的许多查询工具。
  • mongo可以直接运行用JavaScript编写的与MongoDB数据库交互的程序。
    • 通过mongo可以使用JavaScript与MongoDB进行交互,并可将这些脚本保存为.js文件,以便在需要的时候运行。事实上,mongo控制台中的许多内置命令都是用JavaScript编写的。
    • 可以将在命令shell中输入的许多命令添加到一个扩展名为.js的文件中,启动shell时,以添加该文件名到命令行或者从shell中使用load()函数的方式运行它们。shell将执行文件的内容,然后退出。

2、备份MongoDB

  • 创建两个数据库,并各插入一条数据。
> use db1
switched to db db1
> db.people.insert({"name":"zhangsan", "age":11, "addr":"shanghai"})
WriteResult({ "nInserted" : 1 })

> use db2
switched to db db2
> db.media.insert({"Type":"CD", "Artist":"Nirvana", "Title":"Nevermind", "Genre":"Grunge", "Releasedate":"1991.09.24", "Tracklist":[{"Track":"1", "Title":"Smells Like Teen Spirit", "Length":"5:02"}, {"Track":"2", "Title":"In Bloom", "Length":"4:15"}]})
WriteResult({ "nInserted" : 1 })

2.1、备份MongoDB

  • 默认情况下,mongodump连接到本地MongoDB(默认端口),并备份所有的数据库和集合,并将备份文件放到当前目录的dump目录中。备份文件的目录结构是./dump/[databasename]/[collectionname].bson。
  • mongodump将数据存储在.bson文件中,将每个集合的索引及其定义都保存在.metadata.json文件中。
  • 注意,mongodump工具在写入备份文件时,不会清空输出目录。
  • mongodump命令的基本使用方法如下
//备份整个MongoDB
mongodump -h <hostname><:port>
//备份指定的数据库
mongodump -h <hostname><:port> -d <DATABASE_NAME>
//备份指定的集合
mongodump -h <hostname><:port> -d <DATABASE_NAME> -c <COLLECTION_NAME>

//备份到指定目录<path>
mongodump -h <hostname><:port> -o <path>

示例:

//将MongoDB备份到指定目录
]# mongodump -o /data/mongodb_dump/

]# ls -l /data/mongodb_dump/
总用量 0
drwxr-xr-x 2 root root 69 9月  15 15:58 admin
drwxr-xr-x 2 root root 53 9月  15 15:58 db1
drwxr-xr-x 2 root root 51 9月  15 15:58 db2

2.2、恢复数据

  • mongorestore命令的基本使用方法如下
//恢复整个MongoDB(默认目录时./dump)
mongorestore -h <hostname><:port>
//恢复指定的数据库
mongorestore -h <hostname><:port> --nsInclude <DATABASE_NAME>.*
//恢复指定的集合
mongorestore -h <hostname><:port> --nsInclude <DATABASE_NAME>.<COLLECTION_NAME>

//从指定目录<path>中恢复数据
mongorestore -h <hostname><:port> --dir=<path>

//在恢复数据前删除每个集合
mongorestore -h <hostname><:port> --drop

示例:

//从指定目录中恢复指定的数据库
]# mongorestore --dir=/data/mongodb_dump/ --nsInclude db2.*

2.3、备份大数据库

  • 使用mongodump备份比较慢,在备份较大的数据库复制集时可能会有些问题(备份期间数据可能被改写,需要将数据库维护在一致的状态,因此备份中不能出现在不同时间点复制的文件)。但是,用来备份单个数据库、集合、子集合还是比较好的方法。
  • 数据库备份系统有一个必杀技,就是时间点快照,它的速度非常快。快照完成的速度越快,数据库服务器被冻结的时间就越短。

1、使用辅助服务器备份数据

  • 从辅助服务器备份数据,在备份期间可以冻结该服务器。备份完成后,重启该辅助服务器,让它从其他服务器获得最新数据。
  • 在MongoDB中创建辅助服务器是非常简单的,并且可以使用MongoDB的复制机制来保证它与主服务器一致。

2、使用文件系统创建快照

  • 存储的逻辑卷管理系统可以在任意时间点创建快照。
  • 在创建快照之后,系统卷或文件系统管理器不会将修改操作写到原来的位置(数据块)。使用快照的过程如下:
    • (1)创建快照。
    • (2)从快照中复制数据或将快照恢复到另一个卷中。
    • (3)释放快照。
  • 支持快照功能的卷管理器有:
    • Linux和LVM卷管理系统
    • Sun ZFS
    • Amazon EBS卷
    • 使用卷影副本的Windows Server
  • 大多数卷管理器都具有快速创建快照的能力,通常只需要数秒时间,即使是在数据量非常大的情况下。此时卷管理器并没有真正复制数据,而是在驱动中插入一个标签。
  • 使用文件系统快照是备份MongoDB的最快捷高效的方式。
  • 如何将MongoDB服务器的状态保持一致时,也将磁盘中的所有数据处于一致的状态。(阻塞写入磁盘,先缓存在内存里)
    • 方法一:将MongoDB的日志文件保存在同一设备上。
    • 方法二:将MongoDB所有未完成的磁盘写入刷新到磁盘并阻塞写入,然后创建快照。
//将MongoDB所有未完成的磁盘写入刷新到磁盘并阻塞写入
> db.fsyncLock()

//查看fsyncLock的状态。fsync进程(负责将修改写入磁盘)正在阻塞写入操作
> db.currentOp()
...
			"desc" : "fsyncLockWorker",
			"active" : true,
...

//快照完成后,释放锁
> db.fsyncUnlock()

3、将数据导入或导出MongoDB

3.1、将数据导出MongoDB

  • mongoexport命令的基本使用方法如下
mongoexport -h <hostname><:port> -d <DATABASE_NAME> -c <COLLECTION_NAME> -q {} -f 'name, age' --type=<type> -o <file>
  -h, --host=<hostname:port>            连接哪个MongoDB服务器
  -d, --db=<database-name>              导出哪个数据库
  -c, --collection=<collection-name>    导出哪个集合
  -f, --fields=<field>[, <field>]*     导出哪些字段,例如'name,age'
  --type=<type>                          输出格式,可以是json或CSV
  -o, --out=<filename>                  输出的文件。如果未指定,则使用stdout

  -q, --query=<json>                    查询过滤器,例如'{x:{$gt:1}}'
  --assertExists                         如果指定,则如果集合不存在,则导出失败
  --skip=<count>                         跳过前n个文档
  --limit=<count>                        只输出前n个文档
  --sort=<json>                          基于字段排序,例如'{x:1}'

示例:

> db.people.find()
{ "_id" : ObjectId("63230c19a8a31a85c31698b7"), "name" : "zhangsan", "age" : 11, "addr" : "shanghai" }
{ "_id" : ObjectId("63230c19a8a31a85c31698b8"), "name" : "lisi", "age" : 22, "addr" : "beijing" }
{ "_id" : ObjectId("63230c19a8a31a85c31698b9"), "name" : "wanger", "age" : 33, "addr" : [ "beijing", "shanghai" ] }
{ "_id" : ObjectId("63230c1aa8a31a85c31698ba"), "name" : "mazi", "age" : 44, "face" : "pock", "addr" : [ "beijing", "shanghai", "guangzhou" ] }

//将中的age大于30的文档导出到people.csv文件中
]# mongoexport -d db1 -c people -q '{"age": {"$gt": 30}}' -f 'name,age' --type=CSV -o people.csv
//同上
]# mongoexport -d db1 -c people -q '{"age": {"$gt": 30}}' -f 'name,age' --type=CSV > people.csv

//查看people.csv文件
]# cat ./people.csv
name,age
wanger,33
mazi,44

3.2、将数据导入MongoDB

  • mongoimport可以将数据直接导入MongoDB服务器的特定集合中。不同于mongorestore,它是从备份文件(二进制数据)中恢复MongoDB。
  • mongoimport工具可加载三种格式的文件:
    • CSV:每行代表一个文档,字段之间用逗号分隔。
    • TSV:与CSV类似于,但使用Tab字符作为分隔符。该格式十分常见,因为它不要求对任何文本字符进行转义(除了换行符)。
    • JSON:每行都包含一块JSON,代表一个文档。与其他格式不同,JSON可以支持可变模式的文档。JSON是默认的输出格式。
  • mongoimport命令的基本使用方法如下
mongoimport -h <hostname><:port> -d <DATABASE_NAME> -c <COLLECTION_NAME> --type=<type> --headerline
  -h, --host=<hostname:port>            连接哪个MongoDB服务器
  -d, --db=<database-name>              导入哪个数据库
  -c, --collection=<collection-name>    导入哪个集合
  --type=<type>                         导入文件的格式:json、csv或tsv
  --headerline                          将导入文件中的第一行作为字段列表(CSV和TSV)
  -f, --fields=<field>[,<field>]*       字段列表,例如'name, age'

  --ignoreBlanks                        忽略CSV和TSV中空值的字段
  --mode=[insert|upsert|merge|delete]   insert:只插入,跳过匹配的文档。
                                        upsert:插入新文档或替换现有文档。
                                        merge:插入新文档或修改现有文档。
                                        delete:只删除匹配的文档。
                                        如果upsert字段匹配多个文档,则只删除一个文档。(默认值:插入)
  --drop                                在插入文档之前删除集合
  --stopOnError                         在导入过程中遇到任何错误后停止。
  -j, --numInsertionWorkers=<number>    可以并发插入文档的数量

示例:

//people.csv文件中的数据导入到数据库db3的集合people中
]# mongoimport -d db3 -c people --type=csv --headerline --file ./people.csv
//同上
]# mongoimport -d db3 -c people --type=csv --headerline < ./people.csv 

//查看数据库db3的集合people
> use db3
switched to db db3
> db.people.find()
{ "_id" : ObjectId("63231669156d8008d1e588c4"), "name" : "wanger", "age" : 33 }
{ "_id" : ObjectId("63231669156d8008d1e588c5"), "name" : "mazi", "age" : 44 }

4、MongoDB的用户和角色

  • MongoDB支持简单的基于角色的身份验证,可以控制用户对数据库的访问(访问级别)。
  • 大多数修改配置或对MongoDB服务器结构进行调整的命令都要在admin数据库中执行,该数据库在每个新的MongoDB安装时自动创建。
    • 在使用管理命令时,必须使用use admin命令切换到admin数据库。
  • 默认情况下,MongoDB不使用任何身份验证方式。任何人都可以连接到MongoDB服务器并执行命令。不过,可以在任何数据库中添加用户,使得在访问数据库时既要求有连接,还需要进行身份验证。
  • MongoDB支持基于角色的访问控制(RBAC)身份验证模型。角色有两种:MongoDB预定义的系统角色和用户自定义的角色。
  • MongoDB预定义的系统角色有(即createUser函数中的role的值):
//数据库用户角色(在所有数据库可用)
read:赋予用户对指定数据库有读权限。
readWrite:赋予用户对指定数据库有读写权限。
//数据库管理角色(在所有数据库可用)
dbAdmin:赋予用户对指定数据库有数据管理权限。例如,该用户可以创建或删除索引、查看统计或访问system.profile集合。
userAdmin:赋予用户对指定数据库有用户管理权限。例如,该用户可以创建、删除和修改用户(仅限于当前数据库)。
dbOwner:赋予用户对指定数据库有最高(所有)权限。包含readWrite、dbAdmin和userAdmin角色的所有权限。
//集群管理角色(只在admin数据库中可用)
clusterManager:赋予用户对集群有管理和监控权限。
clusterMonitor:赋予用户对集群有访问统计信息和收集统计信息的权限。
hostManager:赋予用户对服务器有管理和监控权限。
clusterAdmin:赋予用户对集群有最高(所有)权限。包含clusterManager、clusterMonitor和hostManager角色的所有权限。
//备份和恢复角色(只在admin数据库中可用)
backup:赋予用户在备份MongoDB时所需的最低访问权限。
restore:赋予用户在恢复MongoDB时所需的最低访问权限。
//对所有数据库有效的角色(只在admin数据库中可用)
readAnyDatabase:赋予用户对所有数据库有读权限。
readWriteAnyDatabase:赋予用户对所有数据库有读写权限。
userAdminAnyDatabase:赋予用户对所有数据库有userAdmin权限。
dbAdminAnyDatabase:赋予用户对所有数据库有dbAdmin权限。
//超级用户角色
root:超级角色
  • MongoDB可以对每个数据库的访问进行单独控制,用户和权限信息存储在admin数据库的system.users集合中
    • 如果授权一个普通用户访问两个数据库(例如,db1和db2),必须将凭据和权限都添加到这两个数据库中。
    • 如果在不同数据库为同一用户分别创建了凭据和访问权限,这些记录不会相互同步。换句话说,修改一个数据库中的用户密码不会影响另一个数据库中的用户密码。以这种方式使用用户凭据时,可以创建一个具有密码的主用户。然后在另一个数据库中创建用户,并表明该用户已经存在于主数据库中,并且该用户的凭据应该被用于当前数据库的身份验证。
    • 任何添加到admin数据库中的用户,在所有数据库中都拥有相同的访问权限。不需要为这样的用户单独赋予权限

4.1、查看用户

  • getUsers函数基本语法格式如下
//查看当前数据库的所有用户的信息
db.getUsers( {
   showCredentials: <Boolean>,
   filter: <document>
} )

//查看当前数据库的指定用户的信息
db.getUser( "<username>", {
   showCredentials: <Boolean>,
   showPrivileges: <Boolean>,
   showAuthenticationRestrictions: <Boolean>,
   filter: <document>
} )

//查看所有的用户信息
use admin
db.system.users.find()

示例:

//查看当前数据库的所有用户的信息
> use admin
switched to db admin
> db.getUsers()
[
	{
		"_id" : "admin.admin",
		"userId" : UUID("a79901f3-5896-4159-84d2-ac2bc01ea1f0"),
		"user" : "admin",
		"db" : "admin",
		"roles" : [
			{
				"role" : "readWrite",
				"db" : "admin"
			},
			{
				"role" : "userAdminAnyDatabase",
				"db" : "admin"
			}
		],
		"mechanisms" : [
			"SCRAM-SHA-1",
			"SCRAM-SHA-256"
		]
	}
]

//查看当前数据库的指定用户的信息
> use admin
switched to db admin
> db.getUser("admin")
{
	"_id" : "admin.admin",
	"userId" : UUID("a79901f3-5896-4159-84d2-ac2bc01ea1f0"),
	"user" : "admin",
	"db" : "admin",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "admin"
		},
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}

//查看所有的用户信息
> use admin
switched to db admin
> db.system.users.find()
{ "_id" : "admin.admin", "userId" : UUID("a79901f3-5896-4159-84d2-ac2bc01ea1f0"), "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "e2r/n3ByBHtMSFXxD/vzsA==", "storedKey" : "O5OgKMcMDIfTq6XXCTc6boXc310=", "serverKey" : "o6Fmll+47t9BPhLbTfYgOJFzAwI=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "Z1AavTNtrtNHpKxhDc6yxFeVbD8RVPhJzQPpQg==", "storedKey" : "1o9LmEmHA9RTawsDCKaNbgQxiE8PLcFjylZo2kqHbBs=", "serverKey" : "LbThABxgTH8bc/F31ajt21kwIBVZeWaJLyMYc15T9FY=" } }, "roles" : [ { "role" : "readWrite", "db" : "admin" }, { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }

4.2、添加用户

  • 注意,创建用户时,要先切换到具体的数据库中,再在该数据库执行db.createUser(使用navicat连接时,其中的验证数据库就是该数据库)。
  • createUser函数基本语法格式如下
db.createUser({
  user: "<name>",
  pwd: passwordPrompt(),      // Or  "<cleartext password>"
  customData: { <any information> },
  roles: [
    { role: "<role>", db: "<database>" } | "<role>",
    ...
  ],
  authenticationRestrictions: [
     {
       clientSource: ["<IP>" | "<CIDR range>", ...],
       serverAddress: ["<IP>" | "<CIDR range>", ...]
     },
     ...
  ],
  mechanisms: [ "<SCRAM-SHA-1|SCRAM-SHA-256>", ... ],
  passwordDigestor: "<server|client>"
})
  • createUser函数的参数说明:
    • user:新用户的名称。
    • pwd:用户密码的明文字符串或用passwordPrompt()提示输入用户密码。
    • customData:可选的。任意信息。可用于存储管理员希望与该用户关联的任何数据。例如可以是用户的全名或员工id。
    • roles:授予用户的角色。可以使用空数组[]来创建不包含角色的用户。
    • authenticationRestrictions:可选的。服务器对创建的用户实施的身份验证限制。指定允许用户连接到服务器或服务器可以接受用户的IP地址列表和CIDR范围。3.6新版功能。
    • mechanisms:可选的。指定用于创建SCRAM用户凭证的特定SCRAM机制。如果指定了authenticationmechanics,则只能指定authenticationmechanics的一个子集。
    • passwordDigestor:可选的。指示是服务器还是客户端提取密码。

1、创建管理用户admin

  • 创建一个管理用户admin,就可以使用该账户在admin数据库中添加其他用户,或在任何其他数据库中添加普通用户
//切换到admin数据库
> use admin
switched to db admin

//为admin数据库添加一个用户"admin"
db.createUser({
  user: "admin",
  pwd: "hengha123",
  roles: [
    { role: "readWrite", db: "admin" },
    "userAdminAnyDatabase"
  ]
})

//查看admin数据库中的用户及权限信息
> db.getUsers()
[
	{
		"_id" : "admin.admin",
		"userId" : UUID("113257c7-9a08-47bb-bc3a-bc87ac18ab84"),
		"user" : "admin",
		"db" : "admin",
		"roles" : [
			{
				"role" : "userAdminAnyDatabase",
				"db" : "admin"
			},
			{
				"role" : "readWrite",
				"db" : "admin"
			}
		],
		"mechanisms" : [
			"SCRAM-SHA-1",
			"SCRAM-SHA-256"
		]
	}
]

//查看system.users集合
> db.system.users.find()
{ "_id" : "admin.admin", "userId" : UUID("a79901f3-5896-4159-84d2-ac2bc01ea1f0"), "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "e2r/n3ByBHtMSFXxD/vzsA==", "storedKey" : "O5OgKMcMDIfTq6XXCTc6boXc310=", "serverKey" : "o6Fmll+47t9BPhLbTfYgOJFzAwI=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "Z1AavTNtrtNHpKxhDc6yxFeVbD8RVPhJzQPpQg==", "storedKey" : "1o9LmEmHA9RTawsDCKaNbgQxiE8PLcFjylZo2kqHbBs=", "serverKey" : "LbThABxgTH8bc/F31ajt21kwIBVZeWaJLyMYc15T9FY=" } }, "roles" : [ { "role" : "readWrite", "db" : "admin" }, { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }

2、创建读写用户

  • 创建一个普通用户user1,并赋予可以读写数据库db1的权限。
//切换到db1数据库
> use db1
switched to db db1

//创建一个普通用户user1,并赋予可以读写数据库db1的权限。
> db.createUser({
  user: "user1",
  pwd: "hengha123",
  roles: [
    { role: "readWrite", db: "db1" }
  ]
})

//查看system.users集合
> use admin
switched to db admin
> db.system.users.find()
{ "_id" : "db1.user1", "userId" : UUID("b359cde6-e2a0-45cb-af21-51811733eb87"), "user" : "user1", "db" : "db1", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "93LkQDpugxhB06tRF+/Wig==", "storedKey" : "OYLCG/IMQP4EgMlZU6XIGXrYkLA=", "serverKey" : "FOAYrT3wje3NgGMmaixshGCWguE=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "+xUhbWoSlE/wwgpcrf9SeShzRmW2EsUnHfEOiA==", "storedKey" : "XonHPLyw6lbdAMndbyHDxjODiYz3t1TGkALYDqWAStA=", "serverKey" : "ShLCn2+xaHZJsxPmECCng9cOZBMQAUctdnAZEOQ3HWs=" } }, "roles" : [ { "role" : "readWrite", "db" : "db1" } ] }
...

3、创建只读用户

//切换到db2数据库
> use db2
switched to db db2

//创建一个普通用户user1,并赋予对数据库db2有只读权限。
> db.createUser({
  user: "user2",
  pwd: "hengha123",
  roles: [
    { role: "read", db: "db2" }
  ]
})

//查看system.users集合
> use admin
switched to db admin
> db.system.users.find()
{ "_id" : "db2.user2", "userId" : UUID("5b604472-2072-48a7-80b2-77c9944e73cd"), "user" : "user2", "db" : "db2", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "uKlHqVXyz0HnaqBsE8HI+Q==", "storedKey" : "+imGU/vQGa1QjMzJCzwAuyGOdmQ=", "serverKey" : "3Y12YTIxH68NEuxS2RZvnmihFOk=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "S90dGEo/PFYmdiF9b/MUWW2hxjNMeMGz0o4N/w==", "storedKey" : "+JcssHCLCfvSFHQaNVFYU6tymBM+eoXQ5hfsV3mk2z8=", "serverKey" : "94AabLMkGMSxzjx7IQ7fhs0wRWfeef+s0Y3p5vcqmFA=" } }, "roles" : [ { "role" : "read", "db" : "db2" } ] }
...

4.3、修改用户凭据

  • changeUserPassword函数的基本语法格式如下
//修改指定用户的密码(当前数据库)
db.changeUserPassword(username, password)
  • 使用updateUser()函数可以修改用户访问权限或密码,会更新MongoDB中已有的用户记录。
    • 从技术角度看,可使用任何数据操作命令在system.user中为给定的集合修改用户记录。不过,只有updateUser()函数可以创建密码字段。
    • updateUser()函数为指定的用户提取用户名,再提取文档,为已有用户的任意多个字段定义替换值。
  • updateUser函数的基本语法格式如下
db.updateUser(
   "<username>",
   {
     customData : { <any information> },
     roles : [
       { role: "<role>", db: "<database>" } | "<role>",
       ...
     ],
     pwd: passwordPrompt(),      // Or  "<cleartext password>"
     authenticationRestrictions: [
        {
          clientSource: ["<IP>" | "<CIDR range>", ...],
          serverAddress: ["<IP>", | "<CIDR range>", ...]
        },
        ...
     ],
     mechanisms: [ "<SCRAM-SHA-1|SCRAM-SHA-256>", ... ],
     passwordDigestor: "<server|client>"
   },
   writeConcern: { <write concern> }
)

示例:

//修改admin用户的权限和密码
> use admin
switched to db admin
> db.updateUser(
  "admin",
  {
    roles: [
      { role: "read", db: "admin" },
      "userAdminAnyDatabase"
    ],
     pwd: passwordPrompt()
  }
)

//验证新密码
> use admin
switched to db admin
> db.auth("admin","root123")
1

//查看admin用户的信息,其中一个角色修改了read
> db.getUser("admin")
{
	"_id" : "admin.admin",
	"userId" : UUID("a79901f3-5896-4159-84d2-ac2bc01ea1f0"),
	"user" : "admin",
	"db" : "admin",
	"roles" : [
		{
			"role" : "read",
			"db" : "admin"
		},
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}

4.4、删除用户

  • 注意,在删除用户之前,必须用admin数据库进行身份验证。
  • 删除用户基本语法格式如下
//从当前数据库中删除指定用户
db.dropUser(username, writeConcern)

//从当前数据库中删除所有用户
db.dropAllUsers(writeConcern)

4.5、使用身份验证

  • 使用createUser函数创建用户后,还要在启动MongoDB时启用身份验证

1、启用身份验证

  • 启用身份验证的两种方法:
//方法一,使用mongod命令启动MongoDB时,在启动参数中添加--auth。
//方法二,在mongod.conf中添加如下内容
security:
   authorization: enabled

2、在mongo控制台中执行身份验证

  • auth函数基本语法格式如下
//使用明文密码
db.auth( <username>, <password> )
//提示用户输入密码
db.auth( <username> )

示例:

> use admin
switched to db admin
> show collections
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus

//执行身份验证
> db.auth("admin","hengha123")
1
> show collections
system.users
system.version

5、验证和修复数据

  • 如果服务器意外重启或MongoDB意外崩溃,那么数据可能处于损坏或不完整的状态。
  • 如果数据已损坏可能会出现下面这些情况:
    • MongoDB无法启动,可能是数据文件已经损坏了。
    • 在MongoDB日志中发现断言,或使用db.serverStatus()命令时发现断言数目很大。
    • 查询结果很奇怪或出乎意料。
    • 集合中的记录数目与预期数目不一致。
  • MongoDB有修复或恢复服务的工具,不过,这可能仍然会丢失许多数据,因此要对数据进行备份或部署复制集,以便从灾难中恢复。

5.1、修复服务器

  • 在mongod命令启动MongoDB时,使用--repair参数对MongoDB进行修复。repair操作会消耗很长的时间,并要求使用两倍于MongoDB数据文件大小的空间,这是因为所有的数据都将被克隆到新的文件并重建,这本质上是对所有数据文件进行重建。
  • repair操作的缺点是使用复制集的最好理由之一:
    • 如果需要将某个机器离线并修复,此时不需要完全停止复制集,也仍然可以处理客户端的请求。
  • 为了修复MongoDB,手动启动MongoDB即可。不过,需要在命令的尾部添加--repair参数:
]# mongod --dbpath /apps/mongodb/data/ --repair
  • 注意,mongod --repair对MongoDB修复完成后就会终止该进程。要正式启动MongoDB,只需要移除--repair参数并再次启动即可(启动MongoDB后,从备份中恢复任何丢失的数据)。

5.2、修复集合

  • 有时,可能是MongoDB的数据存在问题。此时,可以使用MongoDB提供的工具判断目标服务器的数据是否损坏。即可以使用validate函数验证数据库中集合的数据是否正常。
  • 如果在验证集合的过程中出现错误(显示在验证文档的errors部分):
    • (1)对数据进行备份。
    • (2)查看MongoDB实例的日志,检查是否存在错误信息。如果有,按照提示完成修复操作。
    • (3)修复操作
      • 修复集合的索引
      • 修复集合的数据(文档)

1、验证集合

  • validate函数的基本语法格式如下
    • 验证集合数据索引是否正确,并返回结果。
db.collection.validate( {
   full: <boolean>,          // Optional
   repair: <boolean>         // Optional, added in MongoDB 5.0
} )
  • validate函数的参数:
    • full:可选的,是否检查所有的文档。为true时,检查所有的文档(速冻慢);为false(默认)时,检查部分文档(速冻快)。
    • repair:可选的,是否进行修复。为true时,进行修复;为false(默认)时,不修复。
  • 从5.0版开始,db.collection.validate()方法还可以修复集合中的不一致。

2、修复集合的索引

  • 如果验证结果显示索引损坏,可以使用reIndex()函数重建受影响集合的索引(建立索引的过程,会阻塞对MongoDB的访问)。
  • db.collection.reIndex()会删除集合上的所有索引,然后重新创建它们。
    • 注意,在使用--repair参数时,也会在数据库的所有集合上运行reIndex()函数。
  • reIndex函数的基本语法格式如下
//自6.0版起弃用
db.collection.reIndex()

3、修复集合的数据(文档)

  • 修复集合中所有文档(也是最危险)的方式有:使用--repair参数或db.repairDatabase()函数。
    • --repair参数会修复所有数据库中的文档,然后重建所有已定义的索引。
    • db.repairDatabase()会修复单个数据库中的所有集合文档,然后重建所有已定义的索引。(阻塞所有读取和写入操作,在万不得已时使用)
#                                                                                                                               #
posted @ 2022-09-15 14:11  麦恒  阅读(73)  评论(0编辑  收藏  举报