Java锁竞争导致sql慢日志原因分析

 更新时间:2022年11月20日 15:40:18   作者:古柏树下  
这篇文章主要介绍了Java锁竞争导致sql慢的日志原因分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

线上在同步用户时,经常出现简单sql的慢日志。根据方法找到代码,发现方法内使用redisson进行锁操作,waiTime和leaseTime都为3秒,数据库操作比较简单,只是一个简单的用户更新操作。代码简化后如下

@Override
@Transactional(rollbackFor = Exception.class)
public LiveMemberResponseDTO becomeStudentNotQueryOrder(LiveBecomeStudentForOrderRequestDTO requestDTO) {
    EduUserEntity user = eduUserService.syncLocalByAccount(requestDTO.getOrderAccountId(), UserRegisterChannel.LIVE_APPLY);
    EduUserEntity applyUser = eduUserService.syncLocalByAccount(requestDTO.getApplyAccountId(), UserRegisterChannel.LIVE_APPLY);
    ...
    ...
    ...
}

调用了更新方法

@Override
@Lock(waitTime = 10000, leaseTime = 3000, value = RedisConstant.USER_SYNC_LOCAL, key = "#accountId")
public EduUserEntity syncLocalByAccount(String accountId, String mobile, String fullName, String source, UserRegisterChannel registerChannel) {
    EduUserEntity eduUserEntity = queryUsersByAccountId(accountId);
    boolean updateFlag = false;
    ....
	....
	....//判断是否需要更新
    if (updateFlag) {
       saveOrUpdate(eduUserEntity);
    }
    return eduUserEntity;
}

由于这里事务里面嵌套了redis锁,并且涉及到更新表,可能会有死锁的情况。通过在获取锁的地方打上地址获取到以下日志

可以看到[Thread-13]在等待了三秒后才获取到redis,根据获取锁的时机,列出表格

事务A(Thread-13)事务B(Thread-14)
获取redis锁
获取db锁
释放redis锁
获取redis锁
尝试获取db锁
尝试获取redis锁
等待三秒
redis锁超时,释放redis锁
成功获取redis锁
完成业务
释放redis和db锁
获取db锁

这是由于两次更新user表过程中,使用了一个事务A,导致事务B来获取db行锁的时候,被事务A阻塞。但在被事务A阻塞前,已经获取到了redis锁,所以导致事务A在获取第二次更新的redis锁的时候被阻塞,造成了死锁。

最终导致,redis锁超时,日志方面体现为慢sql,因为事务B的sql等待了三秒才拿到锁。

这种情况是因为事务和redis锁的嵌套导致,所以指定更新方法的事务传播等级为PROPAGATION_REQUIRED_NEW,不管外层是否存着事务,都开启新事务。

修改后代码

@Override
@Lock(waitTime = 10000, leaseTime = 3000, value = RedisConstant.USER_SYNC_LOCAL, key = "#accountId")
//这里开启新事务
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public EduUserEntity syncLocalByAccount(String accountId, String mobile, String fullName, String source, UserRegisterChannel registerChannel) {
    EduUserEntity eduUserEntity = queryUsersByAccountId(accountId);
    boolean updateFlag = false;
    ....
	....
	....//判断是否需要更新
    if (updateFlag) {
       saveOrUpdate(eduUserEntity);
    }
    return eduUserEntity;
}

声明式事务使用很简单,可以自动帮我们进行事务的开启、提交以及回滚等操作,但是事务的颗粒度是整个方法,无法进行精细化控制。在使用过程中要注意事务的范围与其他中间件的交互,通过指定适当的传播等级来达到效果。

到此这篇关于Java锁竞争导致sql慢日志原因分析的文章就介绍到这了,更多相关Java sql慢日志内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java使用正则表达式匹配获取链接地址的方法示例

    Java使用正则表达式匹配获取链接地址的方法示例

    这篇文章主要介绍了Java使用正则表达式匹配获取链接地址的方法,简单分析了java正则匹配常用方法及获取网址链接的相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • Java入门之集合框架详解

    Java入门之集合框架详解

    本文介绍了Java集合框架体系结构,包括List、Set和Map接口及其常用实现类,重点讲解了ArrayList、LinkedList、HashSet、TreeSet和HashMap等类的使用方法,并详细介绍了泛型的定义和作用,最后,还讨论了集合的遍历和并发修改异常处理
    2025-01-01
  • Java基础之Spring5的核心之一IOC容器

    Java基础之Spring5的核心之一IOC容器

    这篇文章主要介绍了Java基础之Spring5的核心之一IOC容器,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • java中的构造函数什么时候被调用执行

    java中的构造函数什么时候被调用执行

    这篇文章主要介绍了java中的构造函数什么时候被调用执行问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Spring Cloud Config实现分布式配置中心

    Spring Cloud Config实现分布式配置中心

    这篇文章主要介绍了Spring Cloud Config实现分布式配置中心,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • Java解析zip文件,并识别压缩包里面的文件转换成可操作的IO流方式

    Java解析zip文件,并识别压缩包里面的文件转换成可操作的IO流方式

    这篇文章主要介绍了Java解析zip文件,并识别压缩包里面的文件转换成可操作的IO流方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java反射机制原理、Class获取方式以及应用场景详解

    Java反射机制原理、Class获取方式以及应用场景详解

    反射机制是JAVA的核心知识点之一,大多数框架的实现原理就是利用了反射机制,掌握反射机制会使你学习框架更加轻松高效,这篇文章主要给大家介绍了关于Java反射机制原理、Class获取方式以及应用场景的相关资料,需要的朋友可以参考下
    2022-04-04
  • SpringBoot自定义Starter实现流程详解

    SpringBoot自定义Starter实现流程详解

    SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰
    2022-09-09
  • Java RSA加密解密实现方法分析【附BASE64 jar包下载】

    Java RSA加密解密实现方法分析【附BASE64 jar包下载】

    这篇文章主要介绍了Java RSA加密解密实现方法,结合实例形式分析了java基于第三方类库javabase64-1.3.1.jar实现RSA加密解密功能的具体步骤与相关操作技巧,需要的朋友可以参考下
    2017-10-10
  • 手把手教你SpringBoot快速集成Swagger的配置过程

    手把手教你SpringBoot快速集成Swagger的配置过程

    这篇文章主要介绍了手把手教你SpringBoot快速集成Swagger的配置过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02

最新评论