Dubbo 线程污染 PageHelper SQL 莫名多了一个 Limit 子句

博文目录


问题说明

业务报错, 内容是SQL语法错误, 类似这样的, select name from table limit 1 LIMIT 10, 在正常的SQL后面多加了一截 LIMIT 10

通过分析发现, 是因为PageHelper使用不正确导致了这个问题, 详细原因如下

有一段业务代码如下, 在第二行转换Date时因为requestNo字段为null报错, 导致执行了startPage却没有执行SQL, 从而影响了后续SQL的执行, 为什么会影响到后续SQL的执行呢?

PageHelper.startPage(pageNo, pageSize);
Date createdAt = DateTimeKit.parseFromCompactDateTime(request.getRequestNo().subString(0, 14));
List<XxxDO> list = tableMapper.selectByCreatedAt(createdAt);

我们使用的是Dubbo体系, 每一个请求从Dubbo线程池中获取一个线程执行业务, 执行结束后, 线程不会被销毁, 而是归还回Dubbo线程池.

而PageHelper通过使用ThreadLocal保存某个线程下的分页信息, 正常情况下, 第一行保存, 第三行使用并清除. 第二行异常时, 第一行保存, 没有执行第三行, 所以就没有从ThreadLocal中清理掉该线程的信息. 该线程就被归还回了Dubbo线程池

当另一个请求重新使用该Dubbo线程的时候, 执行第一条SQL时, PageHelper检查到ThreadLocal中有该线程的分页信息, 这时就会改写该线程, 添加了一些不可预料的内容, 导致最终报错

问题解决

推荐的解决办法是遵守PageHelper的使用规范, 在分页和执行SQL之间不要有其他的内容, 防止万一, 从根本上避免异常发生

也可以手动从PageHelper的ThreadLocal中移除当前线程的信息, 通过Aop或者抓异常啥的, 但是这个就比较low了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值