记mybatis一级缓存引起的一次oom

记mybatis一级缓存引起的oom


最近做了一个同步数据的需求,需要将代理人学习课程的记录同步至ck,便于数据分析及对应报表查询导出等功能。线上大约十几万代理人,课程五十门左右,累计大约五百万的数据。于是写了个定时任务计算学习结果后插入到clickhouse中。
上代码:
在这里插入图片描述
代码很简单,刚做的时候考虑到数据量较大 没有一次性处理数据,而是分课程去循环处理代理人学习课程的数据,每次根据课程id查出的代理人课程数据也就十几w条,然后再切割数组,每次批量插入一千条,插入完成后,再将此课程数据置空,移除引用, 供GC回收
接下来 开开心心的上线啦
看代码是不是怎么也看不出来会发生oom?
于是,某一天的早晨,告警响起,内存溢出了。

排查过程

之前部署已经设置好了在内存溢出时生成内存快照及gc日志
查看日志发现是上图代码396行发生内存溢出,再一看代码,卧槽, 这地方咋可能内存溢出。
接着将服务器的内存快照下载到本地
使用mat打开内存快照看了一波,找到大对象后
卧槽, 哪来的三百多万的课程对象 懵逼中。。。
在这里插入图片描述
再仔细一看 ,发现了不对劲,怎么是在这个cache对象里面,我没缓存他们呀。。。。
那这个cache对象是干啥的? 查了下, 原来是mybatis的一级缓存
那我之前置空课程对象的代码就没啥用了,对象依然被缓存引用,导致此方法内一直产生的课程对象不能被回收,直到内存被撑爆。。。
在这里插入图片描述

解决方案

可是我都没有用事务,整个方法怎么会公用一个session开启缓存呢?
再仔细看了下代码,类上被加了个事务注解,导致启用事务,但是没几把用(clickhouse不支持事务)。。。
但因为类里面还有其它方法 不能将类上的注解移除
那就只有三种解决办法了

  1. 将此方法移到另外一个类 不开启事务
  2. 在update方法上添加 @Options(flushCache= Options.FlushCachePolicy.TRUE) 清除缓存,也可以手动获取sqlSeession对象调用清除缓存的方法
  3. 每执行一次update方法手动提交一次事务 事务提交后session关闭 一级缓存会自动清除

这里我选择的是第二种方式,在查询课程数据的方法上也加了注解。查询和update都清缓存 因为每次都是查询的不同数据 此处的一级缓存没啥用
至于Options注解和在一个事务内update\select为什么会使用一级缓存(全局开启一级缓存的情况下) 感兴趣的小伙伴可以自行了解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值