在这里先简单的记录一下,详细信息后续再不上;
现在都流行Oracle切换成mysql,公司也在这么做,系统改好进行压测时,发现使用的内存比使用Oracle的程序要大很多;
原来使用Oracle的时候,最初版本是一次性将查询结果,转换成List,然后一条条处理;随着数据量大,偶尔系统会爆出OOM,改变了使用方式,从一次性将查询结果转换成List,改成使用 ResultHandler的方式,同时优化了性能,增加了fetchSize参数,这样一下子节省了大量的内存使用,但切换成MySqL,发现状况又向最初Oracle使用,把查询结果一次性转成List的情况;
最明显的,是使用jvisualvm进行监控时,发现系统的内存一直在涨,只有当系统内存打到最高点的时候,才看到处理的log;这样明显的是 系统将查询结果都装载进客户端后,再调用ResultHandler进行处理;
网上找了一点资料,看MySqL确实是有这个问题,mysql有两种方式:stream方式,以及fetchAll方式;我们现在使用的就是fetchAll方式,一次性将数据加载到内存中;
使用stream方式,看了一下要满足以下几个条件:
- 是否支持cursor read:主要一点满足MySqL的版本:最小5.0.2
- resultSetType=TYPE_FORWARD_ONLY
- resultConcurrency=CONCUR_READ_ONLY
- fetchSize=Integer.MIN_VALUE
只有这样才会进行stream方式,最上面3点是系统缺省的,就是最后一点要在代码里修改的,在查询的xml文件中,增加/修改了一个参数:
fetchSize="-2147483648"
还有文章写到,mysql的链接串,需要设置参数 useCursorFetch=true,否则无效; 暂时没有时间尝试加这个参数和不加这个参数的差别,在做测试的时候,加了这个参数的