Hibernate QueryPlanCache引发的JVM内存泄漏
一、生产环境问题现象
一个经手多人的项目,项目中用到了hibernate作为ORM框架。生产环境中会出现HeapUsage持续缓慢上升的情况,导致触发HeapUsage超过80%的告警(见图1)。
二、问题分析
生产环境dump内存快照(jmap -dump:live,format=b,file=/tmp/dump.hprof $pid)。通过MAT工具进行分析,发现char[]类型数据占比达61.1%(见图2)。List objects char[]类型数据,发现存在很多SQL字符串(见图3),对基本相同的两条SQL字符串进行文字对比,发现只有参数不同(见图4);同时SQL字符串被Hibernate的queryPlanCache持有(见图5)。
至此,可以判断是SQL缓存导致的问题。Google后发现应该是代码中拼接的SQL每次执行时参数不同导致Hibernate重复缓存SQL。全文检索代码,确实找到了问题(见图7)。
三、解决方案
两方面入手:配置+代码
- 修改Hibernate配置
线上稳定第一位,首先修改Hibernate配置,确保生产环境稳定。可以通过修改下面配置实现:
spring:
jpa:
properties:
hibernate:
query:
#controls the maximum number of entries in the plan cache (defaults to 2048)
plan_cache_max_size: 64
#manages the number of ParameterMetadata instances in the cache (defaults to 128)
plan_parameter_metadata_max_size: 32
#Sets the maximum number of strong references held in the cache. e.g. 128 (default)
plan_cache_max_soft_references: 1024
#Sets the maximum number of soft references held in the cache. Set this value to Integer.MAX_VALUE to replicate the behavior of 5.1.1 and earlier. e.g. 2048 (default)
plan_cache_max_strong_references: 64
- 修改问题代码
后续更新。。。。。。
四、测试环境验证
进行中,后续更新。。。。。。
五、生产上线
后续更新。。。。。。
六、总结
后续更新。。。。。。
项目中不止这一个问题,还需要一个一个解决
- 缓存应该用WeakReference或SoftReference
- 分布式系统资源配额
七、参考
- Hibernate文档
- https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/5/html/hibernate_core_reference_guide/configuration-optional
- https://www.codenong.com/31557076/
- https://www.thinbug.com/q/31557076
- https://blog.csdn.net/qq_38425719/article/details/103856377
- https://blog.csdn.net/dream_lixiang/article/details/77248292