记一次并发锁超时排查

背景:用户需求需要批量走流程,但单线程走流程速度比较慢,10条的话需要花费10倍的时间,故改成多线程模式;改成多线程模式之后遇到多种bug;

1、处理完成之后,刷新页面,流程数据还没保存完成导致刷新页面错误
解决方法:主线程延迟500ms 返回。

2、jpa方式下,并且主线程等待子线程完成之后返回。会导致子线程里面修改的值被主线程覆盖掉。
伪代码例子:

public class A{
 @Autowired
 private B b;
	public test(id){
		b.test(id);
		new Thread(new Runnable(){
			@OverWrite
			public void run(){
				Entity entity = entityDao.findById(id);
				entity.setName("A");
				entityDao.save(entity);
			}	
		}).start();

		Thread.currentThread().sleep(500);
    }   
}

public class B{
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public test(id){
		Entity entity = entityDao.findById(id);
		entity.setName("B");
		entityDao.save(entity);
	}
}

public class Entity{
	private String id;
	private String name;
}

得到结果是B,所以猜测@Transactional事务是在线程结束时候提交。待验证。

3、并发处理流程会导致数据库锁超时问题。由于公司采用注解方式封装业务流程,封装比较重,故流程容易死锁。
问题的具体排查:
1、首先通过下面的sql排查问题

SHOW OPEN TABLES WHERE In_use > 0;

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; 

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; 

SELECT * from `performance_schema`.events_statements_current;

SELECT * from `performance_schema`.threads;

SELECT * from information_schema.`PROCESSLIST`;



SELECT b.trx_mysql_thread_id as 'blocked_thread_id' ,b.trx_query AS 'blocked_sql_text' ,c.trx_mysql_thread_id AS 'blocker_thread_id',c.trx_query AS 'blocker_sql_text' 
,f.SQL_TEXT,d.ID,c.trx_started,f.THREAD_ID
from information_schema.INNODB_LOCK_WAITS a
JOIN information_schema.INNODB_TRX b ON a.requesting_trx_id = b.trx_id
JOIN information_schema.INNODB_TRX c ON a.blocking_trx_id = c.trx_id
JOIN information_schema.`PROCESSLIST` d ON d.ID = c.trx_mysql_thread_id
JOIN `performance_schema`.threads e ON e.PROCESSLIST_ID = d.ID
JOIN `performance_schema`.events_statements_current f  ON f.THREAD_ID = e.THREAD_ID;

最后发现,同一个线程,获取@Aspect切面的参数存在并发问题:

classA:thread:Thread-221; instanceId:10775658
classB:thread:Thread-221; instanceId:10775667
classC:thread:Thread-221; instanceId:10775658

接下来具体排查为什么不一致问题。

再由于 采用分布式锁,会等所有线程成功再一起提交。
故线程1锁住了 表的10775667。线程2也要操作10775667,需要等待线程1提交。而线程1需要等待线程2提交。造成死锁。
后面通过日志打印排查。发现入参是共享的参数,导致属性覆盖。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值