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()会修复单个数据库中的所有集合文档,然后重建所有已定义的索引。(阻塞所有读取和写入操作,在万不得已时使用)
# #