io.shardingsphere的3.X版本与pagehelper同时使用时导致offset始终为0的问题

继上一次将分库分表的依赖由3.0.0.M3的版本替换为3.1.0以支持数据库域名中带下划线后,又遇到另一个坑。

3.1.0版本的依赖如下:

       <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>

问题描述

什么问题呢,具体记不太清了,两个多月前同事遇到的问题,一直忘了整理,因为项目是我负责搭建的,所以跟进解决下。大概就是某一线上应用报错,查看报错日志及sql日志定位到是分页查询的问题。举个例子,若分页大小为10,第1次真正执行的分页查询sql为

select * from XX where XX limit 0 10;

第2次真正执行的分页查询sql为

select * from XX where XX limit 0 20;

......

第10次真正执行的分页查询sql为

select * from XX where XX limit 0 100;

offset始终为0。这导致后继操作执行了一批已经处理过的数据,导致重复处理,业务中在处理已处理过的数据时给予了报错。那是什么原因导致上述问题的产生呢?

问题分析

在解决上述问题时,我们应先了解一件事,我们在使用ShardingSphere进行数据分片时,sql的执行流程时pagehelper->shardinshagsphere->mysql数据库。也就是我们写的不分页查询的sql先被pagehelper改写为分页查询的sql,然后再被shardinshagsphere改写,最后在数据库执行改写后的sql。

有兴趣的可以看下shardingsphere的内核剖析

我们再来看下shardinshagsphere是如何改写的,有兴趣的可以看下shardingsphere的改写引擎

通过以上,猜测可能是sharding-jdbc改写了offset和limit,改写并真正执行的分页查询sql为以下形式:

select * from XX where XX limit 0 (offset + limit);

debug源码看下是否真的如此,查看源码:

其中processParameters方法的作用是填充参数及重写limit,其参数List<Object> parameters中包含分页用的offset和limit,真正用于分页的参数也是用的这里的,该方法调用fill和rewrite方法。fill方法用于参数的填充,rewrite方法用于重写limit,可以看到该方法中将List<Object> parameters中的offset重置为0,limit置为offset+limit,与我们上述猜测一致。

这也是io.sharding与pagehelper一起使用时的一个坑,shardinshagsphere用的是3.1.0版本,pagehelper使用的依赖是

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>

也就是使用的是5.1.4版本的pagehelper。

感觉3.1.0版本的shardinioshagsphere与任意版本的pagehelper搭配使用时都会出现这个问题。

解决方式

由于使用io.shardinioshagsphere已经遇到了两个坑,最后选择弃用,改用如下依赖:

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>

其路由时关于分页的代码如下:

可以看出,其不会每次重写offset和limit。实际证明,问题也得到了解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffylv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值