关于在oracle查询密集的情况下OOM问题
线上tomcat运行内存设置为4G,在用户使用密集的情况下oom。
通过内存分析工具(MAT)得到结果如下:
应当是SQL查询结果过大导致,但是SQL查询返回结果并不大。
实际查询结果非常小,只有一条数据,但是SQL较为复杂,关联的表较多。
使用的是oracle提供的jdbc驱动包,在查询的时候会使用defineChars预设大小
defineChars大小的计算公式是这样的:
defineChars大小 = rowSize * rowPrefetchCount
rowPrefetchCount在Oracle中,缺省值为10。
其中rowSize是执行查询设计的每一列的大小的和。计算公式是:
rowSize = col_1_size + col_2_size + ... + col_n_sizes
所以在查询varchar2(4000)之类的设置的列较多的情况下,可能导致defineChars可能就有1MB了。
这个和预想的300MB差距较大,还有一个preparedStatement 在不断地复用(就是做了缓存),在dbcp中为-1,那么就是不做限制。
所以在缓存的情况下,对象一直被引用,导致JVM无法完成GC,最终导致OOM。
解决方法就是设置相关的配置,例如
spring.datasource.max-open-prepared-statements指定最大的打开的prepared statements数量.
spring.datasource.pool-prepared-statements指定是否池化statements.
等。