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
- 创建两个数据库,并各插入一条数据。
1 2 3 4 5 6 7 8 9 | > 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命令的基本使用方法如下:
1 2 3 4 5 6 7 8 9 | //备份整个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> |
示例:
1 2 3 4 5 6 7 8 | //将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命令的基本使用方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 | //恢复整个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 |
示例:
1 2 | //从指定目录中恢复指定的数据库 ]# 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所有未完成的磁盘写入刷新到磁盘并阻塞写入,然后创建快照。
1 2 3 4 5 6 7 8 9 10 11 12 | //将MongoDB所有未完成的磁盘写入刷新到磁盘并阻塞写入 > db.fsyncLock() //查看fsyncLock的状态。fsync进程(负责将修改写入磁盘)正在阻塞写入操作 > db.currentOp() ... "desc" : "fsyncLockWorker" , "active" : true, ... //快照完成后,释放锁 > db.fsyncUnlock() |
3、将数据导入或导出MongoDB
3.1、将数据导出MongoDB
- mongoexport命令的基本使用方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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}' |
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | > 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命令的基本使用方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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> 可以并发插入文档的数量 |
示例:
1 2 3 4 5 6 7 8 9 10 11 | //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的值):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //数据库用户角色(在所有数据库可用) 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函数基本语法格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //查看当前数据库的所有用户的信息 db.getUsers( { showCredentials: <Boolean>, filter: <document> } ) //查看当前数据库的指定用户的信息 db.getUser( "<username>" , { showCredentials: <Boolean>, showPrivileges: <Boolean>, showAuthenticationRestrictions: <Boolean>, filter: <document> } ) //查看所有的用户信息 use admin db.system.users.find() |
示例:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | //查看当前数据库的所有用户的信息 > 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函数基本语法格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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数据库中添加其他用户,或在任何其他数据库中添加普通用户。
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 37 38 39 40 41 42 | //切换到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的权限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //切换到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、创建只读用户
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //切换到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函数的基本语法格式如下:
1 2 | //修改指定用户的密码(当前数据库) db.changeUserPassword(username, password) |
- 使用updateUser()函数可以修改用户访问权限或密码,会更新MongoDB中已有的用户记录。
- 从技术角度看,可使用任何数据操作命令在system.user中为给定的集合修改用户记录。不过,只有updateUser()函数可以创建密码字段。
- updateUser()函数为指定的用户提取用户名,再提取文档,为已有用户的任意多个字段定义替换值。
- updateUser函数的基本语法格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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> } ) |
示例:
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 37 38 39 40 41 42 | //修改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数据库进行身份验证。
- 删除用户基本语法格式如下:
1 2 3 4 5 | //从当前数据库中删除指定用户 db.dropUser(username, writeConcern) //从当前数据库中删除所有用户 db.dropAllUsers(writeConcern) |
4.5、使用身份验证
- 使用createUser函数创建用户后,还要在启动MongoDB时启用身份验证。
1、启用身份验证
- 启用身份验证的两种方法:
1 2 3 4 | //方法一,使用mongod命令启动MongoDB时,在启动参数中添加--auth。 //方法二,在mongod.conf中添加如下内容 security: authorization: enabled |
2、在mongo控制台中执行身份验证
- auth函数基本语法格式如下:
1 2 3 4 | //使用明文密码 db.auth( <username>, <password> ) //提示用户输入密码 db.auth( <username> ) |
示例:
1 2 3 4 5 6 7 8 9 10 11 | > 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参数:
1 | ]# mongod --dbpath /apps/mongodb/data/ --repair |
- 注意,mongod --repair对MongoDB修复完成后就会终止该进程。要正式启动MongoDB,只需要移除--repair参数并再次启动即可(启动MongoDB后,从备份中恢复任何丢失的数据)。
5.2、修复集合
- 有时,可能是MongoDB的数据存在问题。此时,可以使用MongoDB提供的工具判断目标服务器的数据是否损坏。即可以使用validate函数验证数据库中集合的数据是否正常。
- 如果在验证集合的过程中出现错误(显示在验证文档的errors部分):
- (1)对数据进行备份。
- (2)查看MongoDB实例的日志,检查是否存在错误信息。如果有,按照提示完成修复操作。
- (3)修复操作
- 修复集合的索引
- 修复集合的数据(文档)
1、验证集合
- validate函数的基本语法格式如下:
- 验证集合数据和索引是否正确,并返回结果。
1 2 3 4 | 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函数的基本语法格式如下:
1 2 | //自6.0版起弃用 db.collection.reIndex() |
3、修复集合的数据(文档)
- 修复集合中所有文档(也是最危险)的方式有:使用--repair参数或db.repairDatabase()函数。
- --repair参数会修复所有数据库中的文档,然后重建所有已定义的索引。
- db.repairDatabase()会修复单个数据库中的所有集合文档,然后重建所有已定义的索引。(阻塞所有读取和写入操作,在万不得已时使用)
1 | # # |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2021-09-15 运维docker07-docker数据管理