目录
MongoDB 和 SQL 数据库之间的主要区别是:
- 不需要在服务器上创建数据库、集合或字段,因为 MongoDB 将在访问它们时动态创建这些元素。
- MongoDB 中的所有对象和元素名称都区分大小写。
一、控制访问权限
MongoDB 支持简单的基于角色的认证系统,其中包含预定义的系统角色和用户定义的定制角色,通过该系统可以控制用户对数据库的访问及他们被授予的访问级别。大多数修改配置数据或者对结果进行大幅调整的 MongoDB 服务器命令都被限制在专门的 admin 数据库中执行,该数据库将在每个新的 MongoDB 安装时自动创建。
默认情况下,MongoDB 不使用任何认证方式。任何可以访问网络的人都可以连接到服务器并执行命令。不过,可以在任何数据库中添加用户,这样就可以对 MongoDB 进行配置,使得在访问数据库时要求进行服务器验证。
MongoDB 支持对每个数据库的访问进行单独控制,访问控制信息被存储在特有的 system.users 集合中。对于希望访问两个数据库(例如 db1 和 db2 )的普通用户,他们的凭据和权限必须被同时添加到两个数据库中。
如果在不同数据库为同一用户分别创建了登录和访问权限,这些记录不会互相同步。换句话说,修改一个数据库中的用户密码不会影响另一个数据库中的用户密码。该规则有一个例外:任何添加到 admin 数据库中的用户,在所有数据库中都拥有相同的访问权限,不需要为这样的用户单独赋予权限。
1. 添加 admin 用户
> use admin;
switched to db admin
> db.createUser({user : "admin", pwd : "pass", roles: [ { role : "readWrite", db : "admin"
... }, { role: "userAdminAnyDatabase", db : "admin" } ] });
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "readWrite",
"db" : "admin"
},
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
> db.system.users.findOne({user:"admin"})
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "kLpduUuLPNHh5Z8RjuhPnw==",
"storedKey" : "PKPFi5NDRmvDZj88cdSz1ZM+Ffk=",
"serverKey" : "6r0EKeHkjp9pymkLJeLD0+krutY="
},
"SCRAM-SHA-256" : {
"iterationCount" : 15000,
"salt" : "BkiI7zbBQJ0b4LghbuGE0YxmvlbYNX0HryoN/w==",
"storedKey" : "sgNs3puWRadYmxXjfSgoEzlxj1oOwB/Y5RdFQ2HTx5c=",
"serverKey" : "+OLxG/kecq4zoWcOduouoLC1YFhQZ86wS/oMz1EXZ0o="
}
},
"roles" : [
{
"role" : "readWrite",
"db" : "admin"
},
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
>
2. 启用身份认证
可以用以下两种方式启用身份认证:
- 在配置文件(如 mongodb.conf)中添加 auth=true,然后重启 MongoDB。
- 停止服务器并在启动参数中添加 --auth。
3. 在 mongo 控制台中执行身份验证
[mongodb@hdp4~]$mongo
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 4.0.2
> use admin
switched to db admin
> show collections;
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
> db.auth("admin","pass");
1
> show collections;
> db.getUsers();
[
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"roles" : [
{
"role" : "readWrite",
"db" : "admin"
},
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]
>
如果使用 admin 凭证访问 admin 之外的数据库,那么必须首先针对 admin 数据库进行认证,否则无法访问系统中的任何其它数据库。
[mongodb@hdp4~]$mongo
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 4.0.2
> use test
switched to db test
> show collections;
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
> db.auth("admin","pass");
Error: Authentication failed.
0
> use admin
switched to db admin
> db.auth("admin","pass");
1
> use test;
switched to db test
> show collections;
products
>
5. 修改用户凭据
[mongodb@hdp4~]$mongo admin
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 4.0.2
> db.auth("admin", "pass");
1
> use test;
switched to db test
> db.createUser({user : "foo", pwd : "foo" , roles: [ { role : "read", db : "test" } ] } );
Successfully added user: {
"user" : "foo",
"roles" : [
{
"role" : "read",
"db" : "test"
}
]
}
> db.getUsers();
[
{
"_id" : "test.foo",
"user" : "foo",
"db" : "test",
"roles" : [
{
"role" : "read",
"db" : "test"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]
> db.updateUser( "foo", {pwd : "pass", roles: [ { role : "dbAdmin", db : "test" } ] });
> db.getUsers();
[
{
"_id" : "test.foo",
"user" : "foo",
"db" : "test",
"roles" : [
{
"role" : "dbAdmin",
"db" : "test"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]
> db.auth("foo", "foo");
Error: Authentication failed.
0
> db.auth("foo", "pass");
1
>
6. 添加只读用户
[mongodb@hdp4~]$mongo admin
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 4.0.2
> db.auth("admin", "pass");
1
> use test;
switched to db test
> db.createUser({user : "shadycharacter", pwd : "shadypassword" , roles: [ { role : "read", db : "test" } ] } );
Successfully added user: {
"user" : "shadycharacter",
"roles" : [
{
"role" : "read",
"db" : "test"
}
]
}
> db.auth("shadycharacter", "shadypassword");
1
> db.products.findOne();
2018-10-10T16:05:26.084+0800 E QUERY [js] Error: error: {
"ok" : 0,
"errmsg" : "too many users are authenticated",
"code" : 13,
"codeName" : "Unauthorized"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DBCommandCursor@src/mongo/shell/query.js:708:1
DBQuery.prototype._exec@src/mongo/shell/query.js:113:28
DBQuery.prototype.hasNext@src/mongo/shell/query.js:288:5
DBCollection.prototype.findOne@src/mongo/shell/collection.js:254:10
@(shell):1:1
> exit
bye
[mongodb@hdp4~]$mongo test
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/test
MongoDB server version: 4.0.2
> db.auth("shadycharacter", "shadypassword");
1
> db.products.findOne();
{ "_id" : 20, "item" : "large box", "qty" : 20 }
> db.products.insertOne( { _id: 100, item: "large box", qty: 20 } );
2018-10-10T16:05:59.808+0800 E QUERY [js] WriteCommandError: not authorized on test to execute command { insert: "products", ordered: true, lsid: { id: UUID("679644a1-2281-406e-85b1-986948ee04b4") }, $db: "test" } :
WriteCommandError({
"ok" : 0,
"errmsg" : "not authorized on test to execute command { insert: \"products\", ordered: true, lsid: { id: UUID(\"679644a1-2281-406e-85b1-986948ee04b4\") }, $db: \"test\" }",
"code" : 13,
"codeName" : "Unauthorized"
})
WriteCommandError@src/mongo/shell/bulk_api.js:420:48
Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1
Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21
DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:252:9
@(shell):1:1
>
7. 删除用户
[mongodb@hdp4~]$mongo admin
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 4.0.2
> db.auth("admin","pass");
1
> use test;
switched to db test
> db.dropUser("shadycharacter");
true
> db.getUsers();
[
{
"_id" : "test.foo",
"user" : "foo",
"db" : "test",
"roles" : [
{
"role" : "dbAdmin",
"db" : "test"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]
>
二、备份与还原
1. mongodump 的各种备份方式
# 无账号、密码
# 备份所有数据库到 backup 目录下,每个数据库一个文件,除 local 数据库外
mongodump -o backup
# 备份 abc 数据库到 backup 目录下
mongodump -d abc -o backup
# 备份 abc 数据库下的 ddd 集合
mongodump -d abc -c ddd -o backup
# 有账号、密码
# 备份 abc 数据库下的 ddd 集合
mongodump -udba -pdba -d abc -c ddd -o backup
mongodump --host=127.0.0.1 --port=27017 -udba -p --db=abc --collection=ddd -o backup
这里需要注意的是:在认证备份中,比如在 abc 数据库中,需要其有 dba 这个账号才可以执行备份,要是 abc 数据库里没有账号,那么需要在 admin 上认证,再执行需要加 authenticationDatabase 参数指定保存用户凭证的数据库,没有指定则去 -d 指定的数据库认证。最好还是设置专门备份的账号。
mongodump -udba -pdba -d abc --authenticationDatabase admin -o backup # 在 admin 数据库下认证之后再去备份 abc 数据库。
2. mongodump 示例
备份 test 库:
[mongodb@hdp4~]$mongodump -u wxy --authenticationDatabase admin -d test -o ./dump
Enter password:
2018-10-10T10:05:25.831+0800 writing test.products to
2018-10-10T10:05:25.903+0800 done dumping test.products (3 documents)
[mongodb@hdp4~]$
命令执行后生成 ./dump/test 目录和相关文件:
[mongodb@hdp4~]$ll ./dump/test
total 8
-rw-rw-r-- 1 mongodb mongodb 154 Oct 10 10:05 products.bson
-rw-rw-r-- 1 mongodb mongodb 127 Oct 10 10:05 products.metadata.json
[mongodb@hdp4~]$
products 是集合名称。.bson 文件存储集合数据,该文件只是 MongoDB 内部存储的 BSON 格式文件的一个副本。.json 文件存储元数据,包括集合的索引及其定义。mongodump 工具在写入备份文件之前不会清空输出目录中的内容,而只是覆盖同名文件。除非希望覆盖备份中的数据,否则应该在使用 mongodump 之前保证清空目标目录。
3. 自动备份脚本
#!/bin/bash
##########################################
# Edit these to define source and destinations
MONGO_DBS=""
BACKUP_TMP=~/tmp
BACKUP_DEST=~/backups
MONGODUMP_BIN=/home/mongodb/mongodb-4.0.2/bin/mongodump
TAR_BIN=/usr/bin/tar
##########################################
BACKUPFILE_DATE=`date +%Y%m%d-%H%M`
# _do_store_archive <Database> <Dump_dir> <Dest_Dir> <Dest_file>
function _do_store_archive {
mkdir -p $3
cd $2
tar -cvzf $3/$4 dump
}
# _do_backup <Database name>
function _do_backup {
UNIQ_DIR="$BACKUP_TMP/$1"`date "+%s"`
mkdir -p $UNIQ_DIR/dump
echo "dumping Mongo Database $1"
if [ "all" = "$1" ]; then
$MONGODUMP_BIN -o $UNIQ_DIR/dump -u wxy --authenticationDatabase admin
else
$MONGODUMP_BIN -d $1 -o $UNIQ_DIR/dump -u wxy --authenticationDatabase admin
fi
KEY="database-$BACKUPFILE_DATE.tgz"
echo "Archiving Mongo database to $BACKUP_DEST/$1/$KEY"
DEST_DIR=$BACKUP_DEST/$1
_do_store_archive $1 $UNIQ_DIR $DEST_DIR $KEY
rm -rf $UNIQ_DIR
}
# check to see if individual databases have been specified, otherwise backup the whole server to "all"
if [ "" = "$MONGO_DBS" ]; then
MONGO_DB="all"
_do_backup $MONGO_DB
else
for MONGO_DB in $MONGO_DBS; do
_do_backup $MONGO_DB
done
fi
4. mongorestore 的各种还原方式
# 还原 abc 数据库
mongorestore -udba -pdba -d abc backup/abc
# 还原之前先删除原来数据库(集合)
mongorestore -udba -pdba -d abc --drop backup/abc
# 还原 abc 库中的 ddd 集合
mongorestore -udba -pdba -d abc -c ddd --drop backup/abc/ddd.bson
# 还原 abc 库中的 test 集合
mongorestore --host=127.0.0.1 --port=27017 -udba -pdba -d abc -c test --drop backup/abc/test.bson
# 还原 abc 库中的 test 集合到 ooo 集合
mongorestore --host=127.0.0.1 --port=27017 -udba -pdba -d abc -c ooo --drop backup/abc/test.bson
5. mongorestore 示例
恢复整个备份:
[mongodb@hdp4~]$mongorestore --drop -u wxy --authenticationDatabase admin ./dump
Enter password:
2018-10-10T10:06:11.239+0800 preparing collections to restore from
2018-10-10T10:06:11.381+0800 reading metadata for test.products from dump/test/products.metadata.json
2018-10-10T10:06:11.465+0800 restoring test.products from dump/test/products.bson
2018-10-10T10:06:11.541+0800 no indexes to restore
2018-10-10T10:06:11.541+0800 finished restoring test.products (3 documents)
2018-10-10T10:06:11.541+0800 done
[mongodb@hdp4~]$
恢复单个库:
[mongodb@hdp4~]$mongorestore --drop -u wxy --authenticationDatabase admin -d test ./dump/test/
Enter password:
2018-10-10T10:16:22.666+0800 the --db and --collection args should only be used when restoring from a BSON file. Other uses are deprecated and will not exist in the future; use --nsInclude instead
2018-10-10T10:16:22.666+0800 building a list of collections to restore from dump/test dir
2018-10-10T10:16:22.739+0800 reading metadata for test.products from dump/test/products.metadata.json
2018-10-10T10:16:22.781+0800 restoring test.products from dump/test/products.bson
2018-10-10T10:16:22.818+0800 no indexes to restore
2018-10-10T10:16:22.818+0800 finished restoring test.products (3 documents)
2018-10-10T10:16:22.818+0800 done
[mongodb@hdp4~]$
恢复单个集合:
[mongodb@hdp4~]$mongorestore --drop -u wxy --authenticationDatabase admin -d test -c products ./dump/test/products.bson
Enter password:
2018-10-10T10:17:33.139+0800 checking for collection data in dump/test/products.bson
2018-10-10T10:17:33.287+0800 reading metadata for test.products from dump/test/products.metadata.json
2018-10-10T10:17:33.372+0800 restoring test.products from dump/test/products.bson
2018-10-10T10:17:33.449+0800 no indexes to restore
2018-10-10T10:17:33.449+0800 finished restoring test.products (3 documents)
2018-10-10T10:17:33.449+0800 done
[mongodb@hdp4~]$
三、导入与导出
1. mongoimport 的各种导入方式
mongoimport 支持 CSV(逗号分隔)、TSV(TAB分隔)、JSON(支持可变模式)三种文件格式的数据。
mongoimport -udba -pdba -dabc -ciii --authenticationDatabase admin backup/ddd.txt #导入到iii集合
mongoimport -udba -pdba -dabc -ceee --type=csv --headerline --authenticationDatabase admin backup/ddd.csv #csv导入,需要指定headerline
mongoimport -udba -pdba -dabc -ceee --type=csv --headerline --ignoreBlanks --drop --authenticationDatabase admin backup/ddd.csv #不导入空字段,指定ignoreBlanks。
2. mongoimport 示例
[mongodb@hdp4~]$more a.txt
_id,item,qty
20,large box,20
21,small box,55
22,medium box,30
[mongodb@hdp4~]$mongoimport --drop -u wxy --authenticationDatabase admin -d test -c products --type csv --headerline a.txt
Enter password:
2018-10-10T12:44:30.216+0800 connected to: localhost
2018-10-10T12:44:30.287+0800 dropping: test.products
2018-10-10T12:44:30.447+0800 imported 3 documents
[mongodb@hdp4~]$mongo -u wxy --authenticationDatabase admin test --eval "printjson(db.products.find().count())"
MongoDB shell version v4.0.2
Enter password:
connecting to: mongodb://127.0.0.1:27017/test
MongoDB server version: 4.0.2
3
[mongodb@hdp4~]$
3. mongoexport 的各种导出方式
mongoexport -udba -pdba -dabc -cddd --authenticationDatabase admin -o backup/ddd.txt # 导出txt文本
mongoexport -udba -pdba -dabc -cddd -f sno,sname --authenticationDatabase admin -o backup/ddd.txt # 指定字段导出txt文本
mongoexport -udba -pdba -dabc -cddd -f sno,sname --csv --authenticationDatabase admin -o backup/ddd.csv # 导出成csv格式的需要指定字段-f
mongoexport -udba -pdba -dabc -cddd -q '{"sno":{"$gte":5}}' -f sno,sname --csv --authenticationDatabase admin -o backup/ddd.csv # 按照-q里的条件导出
4. mongoexport 示例
> db.products.find();
{ "_id" : 20, "item" : "large box", "qty" : 20 }
{ "_id" : 21, "item" : "small box", "qty" : 55 }
{ "_id" : 22, "item" : "medium box", "qty" : 30 }
>
带条件导出 products 集合:
[mongodb@hdp4~]$mongoexport -u wxy --authenticationDatabase admin -d test -c products -q '{qty:{$gte:30}}' -f _id,item,qty --type=csv -o a.csv
Enter password:
2018-10-10T13:52:02.762+0800 connected to: localhost
2018-10-10T13:52:02.762+0800 exported 2 records
[mongodb@hdp4~]$more a.csv
_id,item,qty
21,small box,55
22,medium box,30
[mongodb@hdp4~]$