关于在oracle查询密集的情况下OOM问题

发布时间 2023-08-28 14:07:32作者: 十黎九夏

线上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.

 

等。