【问题详细描述】
1、通过Java驱动使用DBLob类下载一个170M文件的时候,报出: BaseException: errorCode:-2,Out of Memory
内存不足。
【版本信息】
Version: 1.12, Release: 18733, Build: 2015-04-29-19.01.40
【错误日志】
2016-11-24-16.20.17.102602 Level:ERROR
PID:20789 TID:20841
Function:appendObjs Line:369
File:SequoiaDB/engine/rtn/rtnContext.cpp
Message:
Failed to reallocate buffer for context, rc: -2
2016-11-24-16.20.17.102613 Level:ERROR
PID:20789 TID:20841
Function:_readFromPool Line:565
File:SequoiaDB/engine/rtn/rtnLobStream.cpp
Message:
failed to append data to context-2
2016-11-24-16.20.17.102624 Level:ERROR
PID:20789 TID:20841
Function:read Line:434
File:SequoiaDB/engine/rtn/rtnLobStream.cpp
Message:
failed to read data from pool:-2
2016-11-24-16.20.17.102658 Level:ERROR
PID:20789 TID:20841
Function:_prepareData Line:253
File:SequoiaDB/engine/rtn/rtnContextLob.cpp
Message:
failed to read lob:-2
【问题分析】
1、该版本的sequoiadb在返回一个大于一个128M的lob的时候,会出现OOM的错误。这是一个已知的BUG。
2、问题的具体原因是:引擎中,一个数据段大小为128M,所以context的buffer最大也是128M。当一个lob的大小大于128M时,context的buffer是装不下这个lob的,所以引擎人为地返回Out of memory(-2)错误(此处并不应该使用OOM的错误,容易误导用户往内存不足方向定位问题)。
【解决方法】
1、用户在客户端不要一次读超过128M的lob内容。比如用户要读取170M的lob,可以分成多次读取,然后再在客户端把读取的内容重新组装为一个170M的lob。这样就可以避免context中128M大小的buffer不够用的情况。
【参考】
用户最终解决方法如附件(分批读取lob.png);
用户的实现方法中,需要将一个170M的文件全部缓存在客户端,然后再一次性写入到输出流中。这种做法在单线程、且客户端机器内存充足的情况下,是可行的。但是,更多情况下我们应该直接将读取到的内容往输出流中写入。
【其他相关】
1、打开一个Lob使用后,一定要执行Lob的close()方法,否则容易因为context泄露而造成Out of Memory(OOM)。
2、使用cursor之后,也需要执行游标的close()方法,否则容易因为context泄露而造成Out of Memory(OOM)。
3、一般没关游标或者没关lob会造成context泄露,此时,执行db.snapshot(SDB_SNAP_CONTEXTS)可以看到有大量的context没有释放。
4、重启coord节点可以释放服务端的context资源。具体做法如下:
1)每台机器上运行一下 bin/sdbstop -r coord 停止该机器上的所有coord;
2)每台机器上运行一下 bin/sdbstart -r coord 启动该机器上的所有coord。
【参考链接】
错误码
常见错误处理指南