栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MyBatisPlus 分页插件的用法和基于行锁的分布式锁方案分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MyBatisPlus 分页插件的用法和基于行锁的分布式锁方案分析

背景

前段时间跟踪 MyBatis 源码,分析 MyBatis 的分页查询结果后,发现传入的 IPage 参数结果已经包含了查询数据了,以为分页查询语句的关键在于第一个入参必须是 IPage ,而不需要返回值了呢。

昨天发现不是这么回事儿,本文再回顾一下 MyBatis 分页插件的用法及三个发现:

    分页查询 DAO 方法的返回值和第一个入参类型必须是 IPage 。IPage 分页参数中的 size 配置,一页只能查 500 条数据,也就是说 size > 500 后分页参数就失效了。怎么解?数据库行锁被锁定后,其他事务会怎么样?

本文讲解答上面三个问题。

MyBatis 分页查询用法

第一步,设置分页查询插件。

@Configuration
public class MyBatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

第二步,编写分页查询 DAO 方法:

IPage queryByPage(IPage iPage, @Param("state") int state);

该方法执行完成后,查询数据会存储到 iPage 参数中,可以直接获取方法返回值。值得注意的是,这个方法必须有返回值。

我最初以为,查询结果都存储到参数中了,是不是方法定义中可以不用返回值了。昨天编码时就随手写成这样了:

void queryByPage(IPage iPage, @Param("state") int state);

结果,执行报 了 SQL 异常:

org.mybatis.spring.MyBatisSystemException: 
nested exception is org.apache.ibatis.exceptions.TooManyResultsException: 
Expected one result (or null) to be returned by selectOne(), 
but found: 500

纳闷了半天,这分页查询怎么就变成了单条查询了呢?对比旧项目代码,还原分页查询方法,正常了。

结论:MyBatisPlus 分页方法返回值必须是 IPage ,不能为 void 。

MyBatisPlus 分页条数限制

以往页面的分页查询,每页数据都很少,没有发现这个问题。

这次实现的是一个批处理任务,一次处理的数据要尽量大。iPage 分页参数 size 初始设置为 1000,发现日志输出的记录数总是 500 条 ,分页参数失效了,为何呢?

使用客户端连接数据库查询,一次能取 1000 条,而 MyBatisPlus 分页查询,这个 500 条是谁控制的呢?能否修改呢?

答案是: PaginationInterceptor 限制了单页条数 500,如果需要,可以这样修改:

@Bean
public PaginationInterceptor paginationInterceptor(){
    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    paginationInterceptor.setLimit(1000);
    return paginationInterceptor;
}
数据库行锁实现分布式锁

业务要求某个任务设计成多机、并行任务,且要保证数据一致。Quartz 框架的分布式任务只能保证任务被一个节点执行,不符合需求,Spring Task 倒是可以实现。

所以问题就变成分布式锁的设计了,参考 Quartz 的集群方案中的锁机制,实现基于数据库行锁的锁。

没测试基于行锁的分布式锁之前,我以为某个事务执行 select for update 之后,其他事务再对相同记录执行该操作的话,应该会报异常,导致锁获取失败。

测试发现,某条记录被锁定之后,交互流程大概是这样的:

    A 事务执行记录 a 的 select for update 后,未提交事务或者断开连接。B 事务同时执行记录 a 的 select for update时,它会阻塞,进入等待状态。A 事务提交或者连接断开,B 事务就会得到锁。我测试了 A 事务100秒后才提交,此时 B 事务也能再次取到锁,可见它不会异常,而是会阻塞等待。

结论:数据库记录的行锁是排他的,其他事务会阻塞等待。

后记

辛丑年腊月二十八,上述就是今年最后一个工作日的总结。

收拾收拾,准备迎接农历新年!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/719861.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号