# 大量数据库查询导致内存溢出

# 问题现象

用户正在做压力测试,模拟500个人登录,测试系统性健康度。

压测过程中从系统监控发现内存持续上升直至100%,随后系统卡住一段时间,卡顿恢复后内存降至20%,需要分析内存持续上升原因。

通过系统管理员登录,查看系统监控,年老代的内存占用,可以发现持续上涨:

1719479371188.png

最高会到100%,随后系统卡住,进行full gc:

1719479438372.png

系统自动gc后,内存占用又降低到20%,同时看gc次数可以看到非常高,可以判断服务器一直存在:涨内存到100%->full gc->降低到20%左右->涨内存...循环操作。

1719479302172.png

# 分析过程

内存溢出需要分析内存文件,看中间件是否自动生成,如果没有就自行jmap导出。

导出的文件通过MemoryAnalyzer工具 (opens new window)进行分析。

通过分析工具发现,占用内存最大的是WorkThread,内钻分析这个Thread是一个个请求,初步可以怀疑:是客户端发送了很多请求到服务器,每个请求都在进行运算并且占用大量内存。

1719486488563.png

1719486579906.png

上一步确认是请求多,并且每个请求占用大量内存,没有找到源头,下一步是分析内存占满时有哪些线程堆栈,看谁问题最突出。

在内存分析机器上,找到.threads的文件,通过此文件检查线程执行情况:

1719486989405.png

最后通过堆栈分析,登陆堆栈StringUtil.passwordBlacklist存在大量卡在数据库查询的动作,并且出现了374次。了解到数据库查询的表有27万数据,如果全部拉取到内存中就会导致每个线程都占用大量内存而溢出。

1719487038169.png

# 解决方案

了解到这个是定制开发功能,客开进行代码优化,比如: 将数据缓存到内存中,通过内存判断数据;或者增加索引+优化SQL,让查询达到毫秒级。

创建人:het
修改人:het