mongodb磁盘满故障 | 您所在的位置:网站首页 › 怎么查看mongodb空间有多少 › mongodb磁盘满故障 |
mongodb磁盘满 cat /var/log/mongodb/mongodb.log 关键的错误日志: ERROR: Insufficient free space for journal files Please make at least 3379MB available in /var/lib/mongodb/journal or use --smallfiles exception in initAndListen: 15926 Insufficient free space for journals, terminating 查了一下 ERROR: Insufficient free space for journal files 原因是因为 mongo 的 journa 目录下空间小于3379MB。磁盘至少要保证journal目录下有3379MB空间可用。 journal 至少以2G的数量进行增长,当磁盘空间不足时,就会报该错误。 看了一下磁盘占用满了: df -h /dev/sda1 91G 83G 2.8G 97% / 首先按照错误日志中解决的办法是使用 --smallfiles参数,尝试启动数据库服务。 --smallfiles 选项会减少数据文件的初始大小,并将最大大小限制为512MB。 smallfiles也会将每个日志文件的大小从1GB减少到128MB。 如果你有大量的数据库,每个数据库都包含少量的数据,那么建议使用--smallfiles 选项。 smallfiles选项可以引导mongod实例创建大量文件,这会影响较大数据库的性能,实际使用时慎重选择。 如果 journal 目录下日志文件占用空间比较大,可以关闭journal功能、删除journal目录下的文件: vim /etc/mongodb.conf nojournal = true smallfiles = true noprealloc = true rm -rf /var/lib/mongodb/journal/* 重启数据库 service mongodb start 我journal本来就占用不大,主要还是数据库占用磁盘太大。因此我直接先采用日志推荐的--smallfiles启动试试: 在mongodb.service启动参数中加 --smallfiles 参数 vim /lib/systemd/system/mongodb.service ExecStart=/usr/bin/mongod --unixSocketPrefix=${SOCKETPATH} --config ${CONF} $DAEMON_OPTS --smallfiles 修改服务配置文件后,重新加载一下服务配置文件 systemctl daemon-reload 重新启动mongodb服务,启动成功 service mongodb start 重启数据库服务成功,但df查看磁盘占用仍然还是很高,继续尝试解决根本的磁盘占用高的问题。 查看mongodb数据库大小的几种方法: 方法1:show databases,可查看不同数据库的大小 # mongo > show databases; admin 0.078GB db01 63.923GB local 0.078GB mytestdb 16.071GB test 0.578GB 可以看到主要db01和mytestdb数据库比较大。 查看指定数据局的详情: > use mytestdb > db.stats() { "db" : "mytestdb", "collections" : 34, "objects" : 8147600, "avgObjSize" : 261.48154941332416, "dataSize" : 2130447072, "storageSize" : 13551329264, "numExtents" : 138, "indexes" : 32, "indexSize" : 286724144, "fileSize" : 17239638016, "nsSizeMB" : 16, "dataFileVersion" : { "major" : 4, "minor" : 5 }, "extentFreeList" : { "num" : 3, "totalSize" : 761118720 }, "ok" : 1 } 方法2:db.serverStatus().mem # mongo > db.serverStatus().mem { "bits" : 64, "resident" : 115, "virtual" : 165558, "supported" : true, "mapped" : 82666, "mappedWithJournal" : 165332 } mapped:映射到内存的数据大小,大小等同于数据库文件的大小 visze:占用的虚拟内存大小 res:占用的物理内存大小 方法3:mongostat # mongostat connected to: 127.0.0.1 insert query update delete getmore command flushes mapped vsize res faults locked db idx miss % qr|qw ar|aw netIn netOut conn time *0 *0 *0 *0 0 1|0 0 80.7g 162g 111m 0 test:0.0% 0 0|0 0|0 62b 3k 1 20:56:29 *0 *0 *0 *0 0 1|0 0 80.7g 162g 111m 0 test:0.0% 0 0|0 0|0 62b 3k 1 20:56:30 *0 *0 *0 *0 0 1|0 0 80.7g 162g 111m 0 test:0.0% 0 0|0 0|0 62b 3k 1 20:56:31 方法4:直接查看数据库文件路径目录文件的大小 # du -sh /var/lib/mongodb/ 81G /var/lib/mongodb/ 主要是数据库文件较大 接下来主要考虑如何回收磁盘空间。 注意:mognodb删除数据后不会释放占用的磁盘空间给操作系统,即使 drop collection 也不行,除非drop database。 删除数据以后,dbshell 中用命令 db.serverStatus().mem 可以看到磁盘空间占用显示虽然已经释放,但df命令查看OS的空闲磁盘空间没变化,mongodb并没有释放给OS。 准备工作: 方案中可能涉及到有足够的磁盘空间来操作,可以考虑给虚机增加新的磁盘,如果没有条件,也可以考虑ssh mount远程主机磁盘到本地。 我使用ssh mount方式,sshfs安装和远程mount的详细操作方法可以参考:https://blog.csdn.net/sunny05296/article/details/77722081 安装sshfs apt-get install -y sshfs # for ubuntu, 查看是否已安装:dpkg -l |grep wget yum install -y fuse-sshfs # for fedore yum install -y epel-release & yum -y install fuse-sshfs # for Centos 挂载远程网络硬盘 mkdir /remote_dir sshfs -o rw [email protected]:/data/ remote_dir/ 如果要卸载移除网盘使用: fusermount -u /remote_dir 方案1:备份恢复(mongodump & mongorestore)【我采用了该方式】 备份 # mkdir -p /remote_dir/mongo_dump_dir # mongodump -d mytestdb -o /remote_dir/mongo_dump_dir 备份后,目录下会生成数据库文件夹mytestdb,查看一下备份后的实际文件夹大小: # cd /remote_dir/mongo_dump_dir # du -h 1.6G ./mytestdb 源库16G备份删除碎片数据以后,空间占用缩小到1.6G,可见源库中存在大量的删除数据 删除源库 # echo 'db.dropDatabase()' | mongo mytestdb 恢复源库 # mongorestore -d mytestdb /remote_dir/mongo_dump_dir/mytestdb 用同样的方法,我处理完 db01 库会后,大小从 61G 减少到 19G。 如果数据量不大、dump时间不长,或者经常备份有dump文件的情况的下,这种方法很简单方便。 方案2:db.repairDatabase() 【我剩余空间太少,没有尝试该方式】 官方介绍说用:删除数据库的数据以后,需要 dbshell 进入删除了数据的 db 后,执行 db.repairDatabase() 可以回收硬盘空间。 但是要注意风险: 1.在生产上操作如果意外停止可能会造成数据无法恢复的危险。 2.如果磁盘空间不足,小于现在这个db时间占有的空间,这种情况是用不了 db.repairDatabase() 的。 需要注意,db.repairDatabase() 能否执行成功,主要处决于:释放出来的磁盘空间小于释放执行前当前OS剩余的磁盘空间,则能释放成功,否则释放失败。 而我声誉磁盘空间只有2.8G,空闲磁盘太少了, 删除数据再db.repairDatabase()的话,估计失败的概率很大。所以,我直接放弃下面的命令执行: # mongo db01 mongo> db.repairDatabase() 或者执行 mongo> db.runCommand({ repairDatabase: 1 }) 后面这种方法还支持带更多的参数,这里就先不详细介绍了。 方案3:db.copyDatabase 【由于我只有一个mongodb,所以没有采用该方式】 mongo> db.copyDatabase("db_src","db_src_copyed","127.0.0.1:27017") 如果是同一个mongodb拷贝,可以直接用:db.copyDatabase("db_src","db_src_copyed") mongo> use db_src mongo> db.dropDatabase() 完整的语法:db.copyDatabase(fromdb, todb, fromhost, username, password, mechanism) fromdb:源db名,用户必须能够对这个db进行鉴权 todb: 复制到目的mongod的名字,名字可以跟原名字不一样 fromhost: ip:port 如果是同一个mongodb拷贝,这个参数可不要 username: 用户名 password: 密码 mechanism:鉴权方式,MONGODB-CR or SCRAM-SHA-1,如果 db.isMaster().maxWireVersion >= 3,那默认就是 SCRAM-SHA-1,否则默认就是 MONGODB-CR 执行数据库拷贝,源库可能是已经删除过数据的库,由于磁盘不释放,造成磁盘空间的浪费。 通过数据库拷贝命令,拷贝到目的库,不会拷贝碎片,会生成一个最小占用的库(数据库目录下也会同步生成新库的文件)。 拷贝库成功后,就可以使用 db.dropDatabase() 删除源库了。 |
CopyRight 2018-2019 实验室设备网 版权所有 |