在创建数据库之初,会多次加入或删除一些键值。最后为了节省空间,将键名与键值精简一番,但占用空间却只会随着内容增加而增加,却不会反之减小。这样,我的数据库“越长越胖”就成了我的问题,复制做备份也很不方便。终于今天在《实战MongoDB》一书中学到了相关的压紧方法,并试用了一下,以此写篇心得。
在写到压紧修复数据库之前,先从备份说起吧。书中介绍了两种备份方法:1.使用mongodump与mongorestore来备份。大概意思是用mongodump命令将数据库导出BSON文件,然后使用mongorestore再恢复回来。但是制作出的备份并不包含索引,需要恢复数据库后自行完成。并且mongorestore不会删除数据库,如果目前存在所要还原的那个,需要手动添加--drop标识。
第二种方法据称是较为常用的,就是直接复制数据库文件。还原备份速度较快,并且包含索引。唯一问题就是需要数据库锁定,即使在开启journaling的状态下。简单来说就是控制端也许只在内存中执行,并没有对磁盘做出操作,就被复制了。为了保证复制的完备,就需要使用锁定命令。
>use admin
>db.runCommand({fsync:1, lock:true})
确保同步并锁定后,就可以复制当前数据库了。在解锁时,未必能立刻解锁。可用db.currentOp()来查询状态。解锁命令为
>db.$cmd.sys.unlock.findOne()
>("ok":1, "info":"unlock requested")
说完开关锁和备份数据库之后,就该说困扰我的“胖数据”问题了。我使用的db.repairDatabase()命令来修复了我的数据库,空间大小从76G减小到35G,将近一半的空间,可观啊。但问题是时间也比较可观,用了我将近3个小时。书上说对大型数据库要repair的话可能需要几天的时间,所以这是修复受损的最后一道防线。在官网说,开启journaling状态下,理论上永远也不用修复。但是我的64位默认为开启journaling,却还是“越吃越胖”。为了节省时间开销,避免不必要的修复,有专门提供压紧的指令来帮助数据库“减肥”。
>db.runCommand({compact:"spreadsheets"})
若要修复索引
>use cloud-docs
>db.spreadsheets.reIndex()
这里加点说明,压紧或修复是肯定要锁定数据库,所以一般是在从节点上执行compact,之后可以将主节点降级,然后进行修复。如果想要强行在主节点锁死压紧,可以使用force.
>db.runCommand({compact:"spreadsheets",force:true})
这里对目前遇到的修复问题作了一次总结与说明,但是对journaling还有待研究。曾经把它写入log并可以type出来,但是有一次长时间运行后崩溃了。倒出了日志,并禁止写入就又可以运行。所以初步猜测对Log的大小可能也会有限制,等有了深入研究后会后续写出。这里先给出一篇链接。
http://www.kchodorow.com/blog/2012/10/04/how-mongodbs-journaling-works/
13/04 补充说明
> db.yourCollection.runCommand("compact");