事情缘由
协助公司中药网排查内存溢出的问题。这个系统是基于Hibernate3开发的一个药品信息、价格变动、药品咨询新闻相关的网站,90%的操作都是查询。
问题日志
工具排查
Dump堆内存文件,使用MAT进行分析
1、jsp 命令获取应用的pid
2、jmap -dump:format=b,file=/dump.hprof pid
分析后发现:
MAT中已经给出有可能出问题的代码位置。SessionFactoryImpl中的QueryPlanCache的体积特别庞大。占比达到67%。
问题原因
1、SessionFactoryImpl是我程序中直接依赖的,我看到了SessionFactoryImpl中的QueryPlanCache的体积特别庞大,此次的内存溢出问题的罪魁祸首就是它。
2、QueryPlanCache会缓存sql,以便于后边的相同的sql重复编译,如果in后的参数不同,hibernate会把其当成不同的sql进行缓存,从而缓存大量的sql导致heap内存溢出。
3、可以看到是QueryPlanCache导致的,询问开发后确实有很多in语句(基本上可以归结为在IN子句中具有可变数量的值,而Hibernate尝试缓存那些查询计划)
解决方案
通过设置缓存最大值来进行限制。
spring: jpa: properties: hibernate: query: plan_cache_max_size: 64 plan_parameter_metadata_max_size: 32 plan_cache_max_soft_references: 1024 plan_cache_max_strong_references: 64 |