背景
某服务线上16台机器,晚上八点左右有4台机器突然出现fullgc,而且不止一次
处理流程
1)发现机器full gc告警时,立即dump出机器内存快照
2)下线问题机器
3)分析内存快照,找到问题对象
可以看到,com.mysql.jdbc.JDBC42ResultSet这个对象占了大部分的内存空间,这个JDBC42ResultSet是什么呢?可以理解成我们从数据库查询的数据转成的java对象;
由此可以推测,fullgc的原因是出现了大对象的查询,比如全表扫描等
4)查找数据库的日志,定位fullgc时数据库中的慢查询语句,定位到了根因:上游进行压测,对其中一个id生成了大量重复数据,业务代码中按照id查询时,查出了大量数据,瞬间打满了jvm
思考
1、收到fullgc告警时,手动dump时间上相对滞后,可以考虑新增jvm参数,fullgc前后自动dump内存快照
-XX:+HeapDumpBeforeFullGC
-XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=data/xxx.dump
2、可以在使用select的时候 加入limit,避免查询出大量数据