abel533 / Mapper

Mybatis Common Mapper - Easy to use
https://mybatis.io
MIT License
7.33k stars 1.63k forks source link

关于SpringBoot中PageHelper.startPage()的线程安全问题 #715

Open 6haining opened 4 years ago

6haining commented 4 years ago

PageHelper父类PageMethod中使用了 LOCAL_PAGE = java.lang.ThreadLocal 共享线程Page变量。

在新版SpringBoot中,不再像以前普通的Spring项目或旧版SpringBoot那样,每个Request请求,都创建一个新的线程 -> new Thread(),而是使用了线程池来处理每个Request请求。这样就引发了一个问题(BUG),场景举例: SpringBoot线程池中的第一个线程"Thread[XNIO-2 task-1,5,main]"(以下简称“线程一”)。 在某一瞬间或时间段,服务并发量很高,当线程一被用来处理A请求【 分页查询列表,AController的list方法,中调用了 PageHelper.startPage(1, 10); 执行完SQL查询后,并没有调用 PageHelper.clearPage(); 清理Page分页数据 】,紧接着线程一又被用来处理B请求(可能是另一个用户的请求)【 导出Excel,BController的export方法,WHERE条件查询全部数据,不执行分页。 】。 这时候问题就出现了,B请求的导出数据最多只有10条。

abel533 commented 4 years ago

注意看文档中的安全调用

anylys commented 4 years ago

PageMethod

https://pagehelper.github.io/docs/howtouse/#2-%E9%85%8D%E7%BD%AE%E6%8B%A6%E6%88%AA%E5%99%A8%E6%8F%92%E4%BB%B6 这是url,查看线程安全的疑问

Frodez commented 4 years ago

注意看文档中的安全调用

借道问一下,ISelect这个接口没有返回值类型的判断,导致PageHelper.startPage().doSelectPage(ISelect iselect)这个方法的返回值类型是由等号左侧的变量类型推断来决定,但有可能返回值类型和左侧的变量类型并不一致,导致运行时cast抛出异常。请问作者有为ISelect完善返回值类型的计划吗?

Frodez commented 4 years ago

注意看文档中的安全调用

另外我给PageHelper提了一个小小的issue,可以给PageHelper少量的性能提升。 https://github.com/pagehelper/Mybatis-PageHelper/issues/482