我正在做一些测试,看看我们是否可以在MongoDB上使用GridFS来存储未来应用程序的文件;我正在使用10gen的C#驱动程序将80Mb文件“上传”到数据库中。
第一次添加很好,花了大约3秒钟,这在我的测试机上并不算太糟糕;然而,未来相同文件的添加需要更长时间,最多30秒,MongoDB最终告诉我内存耗尽并崩溃。
添加10个文件,大小为80Mb,导致在我的数据库中创建8个文件,然后系统崩溃名为dbaseName.0到dbaseName.7,文件大小从16Mb到512Mb从文件0到5呈指数增长,然后是文件6和7都是512Mb。
这些文件低于2Gb,显然第10次添加文件需要dbase超过2Gb,这超出了我的32位测试版本的限制。
为什么存储800Mb的文件会占用2Gb?有没有我错过的地方?
MongoDB是否经常在RAM中保存整个GridFS?如果是这样的话,磁盘有什么意义呢?如果我的生产服务器上只有32Gb的RAM,那么我只能在GridFS中存储32Gb吗?
我在MongoGridFS对象上使用了EnsureIndexes,并检查了显示为GridFS创建索引的数据库,所以Mongo不应该尝试将整个数据存储区放入RAM中吗?
MongoDB满足了我们的所有需求,但我们需要它能够容纳大型文件集;我错过了一些明显的东西吗?
堆栈追踪:
Mon Oct 15 11:57:15 [conn15] insert busyNow.fs.chunks keyUpdates:0 locks(micros) w:112892 113ms
Mon Oct 15 11:57:15 [conn15] MapViewOfFileEx for /data/db/busyNow.7 failed with errno:8 Not enough storage is available to process this command. (file size is 536608768) in MemoryMappedFile::map
Mon Oct 15 11:57:15 [conn15] busyNow.fs.chunks Fatal Assertion 16166
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\util\assert_util.cpp(124) mongo::fassertFailed+0x75
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\util\mmap_win.cpp(211) mongo::MemoryMappedFile::map+0x4ce
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\mongommf.cpp(182) mongo::MongoMMF::create+0xa3
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\pdfile.cpp(469) mongo::MongoDataFile::open+0x141
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\database.cpp(280) mongo::Database::getFile+0x34f
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\database.cpp(332) mongo::Database::suitableFile+0x129
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\database.cpp(359) mongo::Database::allocExtent+0x41
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\pdfile.cpp(1271) mongo::outOfSpace+0x107
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\pdfile.cpp(1293) mongo::allocateSpaceForANewRecord+0x5d
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\pdfile.cpp(1463) mongo::DataFileMgr::insert+0x493
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\pdfile.cpp(1217) mongo::DataFileMgr::insertWithObjMod+0x33
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\instance.cpp(761) mongo::checkAndInsert+0x72
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\instance.cpp(821) mongo::receivedInsert+0x4cd
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\instance.cpp(434) mongo::assembleResponse+0x62a
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\db\db.cpp(192) mongo::MyMessageHandler::process+0xe8
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\mongo\util\net\message_server_port.cpp(86) mongo::pms::threadRun+0x424
Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\third_party\boost\boost\thread\detail\thread.hpp(62) boost::detail::thread_data<boost::_bi::bind_t<void,void (__cdecl*)(mongo::MessagingPort *),boost::_bi::list1<boost::_bi::value<mongo::MessagingPort *
> > > >::run+0x9Mon Oct 15 11:57:17 [conn15] mongod.exe ...\src\third_party\boost\libs\thread\src\win32\thread.cpp(16707566) boost::`anonymous namespace'::thread_start_function+0x47
Mon Oct 15 11:57:17 [conn15] mongod.exe f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c(314) _callthreadstartex+0x1b
Mon Oct 15 11:57:17 [conn15] mongod.exe f:\dd\vctools\crt_bld\self_x86\crt\src\threadex.c(292) _threadstartex+0x64
Mon Oct 15 11:57:17 [conn15]
***aborting after fassert() failure
Mon Oct 15 11:58:33 [initandlisten] connection accepted from 127.0.0.1:56308 #16 (3 connections now open)
答案 0 :(得分:5)
确定;经过大量搜索后,似乎MongoDB在指数大小的文件中预先分配空间,最多2Gb,之后每个文件将为2G。
http://www.mongodb.org/display/DOCS/Excessive+Disk+Space
我的测试程序在后台文件(.0 - .7等)中添加80Mb文件,并且当数据块开始写入最后一个文件时,Mongo预分配另一个指数大于上一个文件的文件。
所以第一个80Mb文件,填满了16Mb文件,32Mb文件和64Mb后台文件,并且由于元数据占用了更多空间并且必须稍微侵入128Mb文件,这会触发mongo预分配256Mb文件总计496Mb;随着更多文件的添加,预先分配了更多文件,当我的测试机器上出现2Gb时,Mongo无法访问该空间并崩溃。
因此,虽然看起来一个80Mb的文件占用的空间比它应该多得多 - 但它以迂回的方式有意义。
使用--noprealloc运行mongod可以关闭此功能,但建议仅用于测试机器。
感谢您的回复!
答案 1 :(得分:0)
GridFS不会仅将所有文件存储在RAM中。
你有堆栈跟踪还是可以再次重现崩溃?