锁竞争导致的慢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;
}
声明式事务使用很简单,可以自动帮我们进行事务的开启、提交以及回滚等操作,但是事务的颗粒度是整个方法,无法进行精细化控制。在使用过程中要注意事务的范围与其他中间件的交互,通过指定适当的传播等级来达到效果。
锁竞争导致的慢sql分析相关推荐
- Android Systrace 基础知识(10) - Binder 和锁竞争解读
本文是 Systrace 系列文章的第十篇,主要是对 Systrace 中的 Binder 和锁信息进行简单介绍,简单介绍了 Binder 的情况,介绍了 Systrace 中 Binder 通信的表 ...
- oracle latch锁,DTCC:Oracle栓锁竞争与Latch优化实践
[IT168 资讯]4月15日,国内数据库领域唯一的年度盛会,由盛拓传媒IT168网站汇集旗下ITPUB.IXPUB以及ChinaUnix中国三大企业级技术社区优势资源主办的2011数据库技术大会在北 ...
- oracle 收集统计信息会锁表吗,统计信息锁住导致收集统计信息失败引起sql执行异常...
这个是老生产谈的事情,统计信息不准确导致sql执行异常,此次记录的主要是表的统计信息被锁住导致无法正常收集统计信息导致sql执行异常: 收集表的统计信息: SQL> exec DBMS_STAT ...
- oracle tabe unlock_Oracle数据库之统计信息锁住导致收集统计信息失败引起sql执行异常...
本文主要向大家介绍了Oracle数据库之统计信息锁住导致收集统计信息失败引起sql执行异常,通过具体的内容向大家展现,希望对大家学习Oracle数据库有所帮助. 这个是老生产谈的事情,统计信息不准确导 ...
- MySQL Innodb表导致死锁日志情况分析与归纳
案例描述 在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志. 两个sql语句如下: (1)insert into back ...
- ReentrantLock 公平锁和非公平锁加锁和解锁源码分析(简述)
- title: ReentrantLock 公平锁和非公平锁加锁和解锁源码分析(简述) - date: 2021/8/16 文章目录 一.ReentrantLock 1. 构造函数 二.Reentr ...
- mysql 表死锁_MySQL Innodb表导致死锁日志情况分析与归纳
案例描述在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志. 两个sql语句如下:(1)insert into backup ...
- 我的物联网项目(二十七) 分布式锁粗心导致大量阻塞
有天项目中某个业务出现了异常,查询相关日志显示如下: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQ ...
- 多线程编程的锁问题解析(锁竞争死锁活锁及Date Race等)
本文是学习了 Guancheng 大神的文章后,根据文中的相关问题,进行代码分析,并且总结出这篇博客. 原文地址:http://blog.csdn.net/freeelinux/article/det ...
最新文章
- Windows下Libvirt Java API使用教程(二)- 接口使用说明
- Java 并发编程:ThreadLocal 的使用及其源码实现
- Linux 网络配置命令:ip、ss
- perl6 中将 字符串 转成十六进制
- 唐骏《我的成功也可以复制》1,盖婚房
- SAP Kyma上创建的Lambda function背后的技术实现
- mysql命令行执行外部文件
- 重新学习的HTTP协议
- c++模板---3(类模板碰到继承问题,类模板类外实现,类模板与友元函数)
- 运算符优先级 必熟记,放到心里
- 使用Jmeter对mysql进行性能测试入门
- 2.2.1.处理机调度的概念,层次
- 使用PPMI改进共现矩阵
- 导入web项目运行报错找不到包
- Hadoop 安装教程
- 西电软件工程概论复习纲要
- 全球及中国石油天然气开采行业产量情况及十四五开发战略规划报告2021年版
- 【Google】谷歌搜索高级用法:包括指定文件类型
- python3下使用有道翻译网页版实现翻译功能~~~附源码
- 匿名发脉脉的拼多多员工,是如何被发现的?背后真相令人发指...