MongoDB笔记: 安装和常见问题
安装
在Centos7下以tgz形式安装.
下载安装包
现在最新的版本是4.2.2, 但是客户端Robot3T现在对4.2的支持不太好, 所以还是使用4.0版本, 下载的是最新的4.0.14: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.14.tgz
安装步骤
# 解压 tar zxvf mongodb-linux-x86_64-rhel70-4.0.14.tgz # 移动到/opt/mongodb mv mongodb-linux-x86_64-rhel70-4.0.14 /opt/mongodb/ cd /opt/mongodb/ # 将其软链到 /opt/mongodb/latest ln -s mongodb-linux-x86_64-rhel70-4.0.14 latest
在/opt/mongodb/latest/下创建配置文件 mongod.conf, 这里没有启用用户名验证, verbosity一开始可以设为2, 安装启动没问题再改回0
storage: dbPath: /data/mongodb/data journal: enabled: true systemLog: destination: file path: "/data/mongodb/mongod.log" verbosity: 0 logAppend: true net: bindIp: "172.17.5.10" port: 27017
创建相应的用户, 目录, 并设置好权限
# 将mongodb的可执行文件软链到bash路径中 ln -s /opt/mongodb/latest/bin/* /usr/local/bin/ # 创建用户 useradd mongod # 创建对应的目录并设置用户 cd /data/ mkdir -p mongodb/data chown -R mongod:mongod mongodb/
创建systemd服务文件, 并添加到开机启动中
vi /lib/systemd/system/mongodb.service systemctl list-unit-files systemctl enable mongodb.service systemctl start mongodb systemctl status mongodb
mongodb.service的内容
[Unit] Description=An object/document-oriented database Documentation=man:mongod(1) After=network.target [Service] User=mongod Group=mongod ExecStart=/usr/local/bin/mongod --quiet --config /opt/mongodb/latest/mongod.conf [Install] WantedBy=multi-user.target
Docker安装
通过Docker安装, 并设置端口映射和连接账号
docker run -d --name mongo -v /data/mongo:/mongo -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123123 mongo:4.0.19-xenial
Ubuntu20.04安装
因为robo3t只支持到4.2, 所以需要在Ubuntu20.04上安装4.2版本. 通过apt安装
# wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add - # echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.list # sudo apt update # apt-cache search mongodb # sudo apt install mongodb-org
然后通过 sudo systemctl (is-enabled|enable|start) mongod 进行服务检查和管理
Ubuntu20.04安装客户端Robo3T
从 https://www.robomongo.org/ 下载最新的社区版, 目前是 1.4.2, 解压缩后放入 /opt/robo3t, 建立软链 /opt/robo3t/latest 指向此目录, chown -R 为root
创建桌面图标, 需要去下载一个png放入bin目录, 创建文件~/.local/share/applications/robo3t.desktop
[Desktop Entry] Version=1.4.2 Type=Application Name=Robo3T Icon=/opt/robo3t/latest/bin/robo3t.png Exec="/opt/robo3t/latest/bin/robo3t" Comment=Robo3T Categories=Development; Terminal=false
备份脚本
备份后压缩, 并只保留最新的60个备份文件
#!/bin/sh MAXIMUM_BACKUP_FILES=60 BASE_FOLDER="/data/backup/mongo_dump" # mongodb config DB_HOSTNAME="172.17.5.10" DB_PORT="27017" DB_USERNAME="" DATABASES=( "rikyplus" ) EXCLUDED_TABLES=( ) #========= echo "MongoDB Backup Task" CURRENT_DATE=$(date +%Y%m%d-%H%M) DUMP_FOLDER="${DB_HOSTNAME}_${CURRENT_DATE}" BACKUP_FOLDER="${BASE_FOLDER}/${DUMP_FOLDER}" mkdir $BACKUP_FOLDER count=0 while [ "x${DATABASES[count]}" != "x" ];do count=$(( count + 1 )) done echo "[+] ${count} databases will be dumped..." # do the dump for DATABASE in ${DATABASES[@]};do echo "[+] Dumping: ${DATABASE}" IGNORED_TABLES_STRING='' for TABLE in "${EXCLUDED_TABLES[@]}";do IGNORED_TABLES_STRING+=" --excludeCollection=${TABLE}" done echo -n " Began: ";echo $(date) if $(mongodump -h ${DB_HOSTNAME}:${DB_PORT} -d ${DATABASE} -o ${BACKUP_FOLDER} ${IGNORED_TABLES_STRING});then echo " Dumped successfully" else echo " Failed dumping this database" fi echo -n " Finished: ";echo $(date) done # Compress to tar ball echo echo "[+] Packaging and compressing the backup folder..." if $(tar -czf ${BACKUP_FOLDER}.tar.gz -C ${BASE_FOLDER} ${DUMP_FOLDER});then rm -rf ${BACKUP_FOLDER} echo " Compressed successfully" else echo " Failed compressing this dump" fi echo -n " Finished: ";echo $(date) # Remove the oldest one BACKUP_FILES_MADE=$(ls -l ${BASE_FOLDER}/*.tar.gz | wc -l) BACKUP_FILES_MADE=$(( $BACKUP_FILES_MADE - 0 )) echo echo "[+] There are ${BACKUP_FILES_MADE} backup files" if [ $BACKUP_FILES_MADE -gt $MAXIMUM_BACKUP_FILES ];then REMOVE_FILES=$(( $BACKUP_FILES_MADE - $MAXIMUM_BACKUP_FILES )) echo "[+] Remove ${REMOVE_FILES} old backup files." ALL_BACKUP_FILES=($(ls -t ${BASE_FOLDER}/*.tar.gz)) EXPIRED_FILES=("${ALL_BACKUP_FILES[@]:${MAXIMUM_BACKUP_FILES}:${BACKUP_FILES_MADE}}") echo "[+] Removing the expired backup files..." for FILE in ${EXPIRED_FILES[@]};do rm -f ${FILE} done fi echo -n " Finished: ";echo $(date)
系统配置
设置ulimit
MongoDB的文件机制
- 每个Collection会单独创建一个数据文件(collection-xxxxxx.wt)
- 每个索引会单独创建一个文件(index-xxxxxx.wt)
- 每个Collection至少需要一个数据文件和一个默认索引(_id索引)
这样每创建1个Collection会占用2个文件句柄, 还需要包含MongoDB自身需要使用的句柄(内部文件如wiredTiger.wt之类, 加上网络连接), 所以Collection的数量是受系统限制的. MongoDB推荐的方式是分片, 不是分库分表. 会造成的问题比如重启时间会很长, 这不是MongoDB推荐的使用方式.
在句柄消耗达到系统上限后, 会报directory-sync: open: Too many open files错误, 并导致mongod崩溃退出. 增加限制需要修改/etc/security/limits.conf (或者 /etc/security/limits.d/20-nproc.conf), 增加或修改为以下内容
* soft nofile 10240 * hard nofile 10240 * soft nproc 10240 * hard nproc 10240 root soft nproc unlimited
需要重启, 用 ulimit -n 检查
MongoDB的用户管理和权限配置
认证机制
MONGODB-CR
官方自定义实现认证机制,通过用户名和密码,通过challenge-response方式,来识别和验证授权。
SCRAM-SHA-1
3.0之后默认的认证模式,通过用户名和密码认证,IETF标准:RFC 5802, 相比较而言, SCRAM-SHA-1认证机制有更好的安全性.
配置访问控制
用户管理员账户和数据库管理员账户都是在数据库 admn 中创建的。在 MongoDB 服务器中启用身份验证后,要以用户管理员或数据库管理员的身份连接到服务器,必须向 admin 数据库验证身份,然后在每个数据库中创建用户账户,让这些用户能够访问该数据库。
创建用户管理员账户
用户管理员应只有创建用户账户的权限,而不能管理数据库或执行其他管理任务。这确保数据库管理和用户账户管理之间有清晰的界限。
第一步是创建用户管理员账户。在 admin 数据库中,添加一个用户并赋予userAdminAnyDatabase角色,userAdminAnyDatabase只在admin数据库中可用,赋予用户所有数据库的userAdmin权限。用户管理员应只有创建用户账户的权限,而不能管理数据库或执行其他管理任务。要创建某个库的管理用户,必须在 admin 进行认证,给哪个库创建用户就先切换到哪个库下面。
[root@mbasic ~]# mongo MongoDB shell version: 3.2.6 connecting to: test > use admin switched to db admin > db.createUser( ... { ... user: "myUserAdmin", ... pwd: "abc123", ... roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] ... } ... ) Successfully added user: { "user" : "myUserAdmin", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
开启权限验证
编辑配置文件/etc/mongod.conf,修改内容如下:
security: authorization: enabled
重启mongodb服务后,客户端连接到服务器时必须提供用户名和密码。另外,从 MongoDB shell 访问 MongoDB 服务器时,如果要添加用户账户,必须执行下面的命令向数据库 admin 验证身份:
> use admin switched to db admin > db.auth("myUserAdmin","abc123") 1 >
也可以在启动 MongoDB shell 时使用选项-u和-p向数据库 admin 验证身份:
mongo -u "myUserAdmin" -p "abc123" --authenticationDatabase admin
创建数据库管理员账户
要创建数据库管理员,可在 MongoDB shell 中切换到数据库 admin,再使用方法createUser添加角色为readWriteAnyDatabase、dbAdminAnyDatabase和clusterAdmin的用户。这让这名用户能够访问系统中的所有数据库、创建新的数据库以及管理 MongoDB 集群和副本集。
创建一个名为 dbadmin 的数据库管理员:
> use admin switched to db admin > db.createUser( ... { ... user: "dbadmin", ... pwd: "abc123", ... roles: [ "readWriteAnyDatabase", "dbAdminAnyDatabase","clusterAdmin" ] ... } ... ) Successfully added user: { "user" : "dbadmin", "roles" : [ "readWriteAnyDatabase", "dbAdminAnyDatabase", "clusterAdmin" ] }
数据库管理员能够访问系统中的所有数据库、创建新的数据库以及管理 MongoDB 集群和副本集。如果要求管理其他数据库,首先要去 admin 库里面去认证。
创建普通用户
经过认证的用户管理员可以使用db.createUser()去创建额外的用户。你可以分配mongodb内置的角色或用户自定义的角色给用户。这个 myUserAdmin 用户仅仅只有特权去管理用户和角色,如果你试图执行其他任何操作,例如在 test 数据库中的foo集合中去读数据,mongodb将返回错误。
你创建用户的数据库(这里就是test数据库)是该用户认证数据库。尽管用户认证是这个数据库,用户依然可以有其他数据库的角色。即用户认证数据库不限制用户权限。
创建一个角色为readWrite的用户 test1 来读写数据库test, 如果需要test的所有权限, 可以使用角色dbOwner
[root@mbasic ~]# mongo MongoDB shell version: 3.2.6 connecting to: test > use admin switched to db admin > db.auth('myUserAdmin','abc123') 1 > use test switched to db test > db.createUser( ... { ... user:"test1", ... pwd: "test1", ... roles: [{ role: "readWrite", db: "test"}] ... } ... ) Successfully added user: { "user" : "test1", "roles" : [ { "role" : "readWrite", "db" : "test" } ] }
创建备份和恢复用户
备份和恢复用户的角色是backup和restore, 这两个角色只存在于admin, 所以必须在admin表创建, 且角色对应的db必须是admin,
db.createUser( { user: 'bbuser', pwd: 'bbpassword', roles: [ { role: "dbAdmin", db: "somedb" }, { "role" : "backup", "db" : "admin" }, { "role" : "restore", "db" : "admin" } ], mechanisms : ["SCRAM-SHA-1"] } )
在使用时, 需要将authenticationDatabase 指向 admin
mongorestore -h 192.168.1.111:27017 -d somedb --objcheck --stopOnError --gzip backup_20200728/ -ubbuser -pbbpasswd --authenticationDatabase admin