文章目录
- 参考文章
- 问题描述
- 解决办法
- 办法1. 新增查询操作
- 办法2. 判断实际事务场景
- 解决办法
参考文章
MySql Lock wait timeout exceeded该如何处理?
AopContext.currentProxy()的使用
问题描述
同一事务内包含对同一条记录进行新增、更新操作,导致mysql锁问题
解决办法
办法1. 新增查询操作
办法2. 判断实际事务场景
判断业务场景是否需要将新增和更新操作放在同一事务内,如果不需要,将事务抽取出来。
这里可能会出现一个问题:通过@Autowird注入的方法调用时,内部事务失效
内部事务:
解决办法
AopContext.currentProxy() // 获取代理对象
AopContext.currentProxy()的使用
为什么能够切入目标对象,原理就是创建了代理类,在代理类中调用目标方法前后进行切入;假如代理对象是 p r o x y 0 , 对于 B 方法 proxy0,对于B方法 proxy0,对于B方法proxy0.B(),执行流程就是先记录日志再调用目标对象s的B方法,所以可以切入;但是A方法 p r o x y 0. A ( ) ,只能对 A 方法增强, A 里面调 B 的时候使用的是 s 目标对象 s . B ( ) ,而不是 proxy0.A(),只能对A方法增强,A里面调B的时候使用的是s目标对象s.B(),而不是 proxy0.A(),只能对A方法增强,A里面调B的时候使用的是s目标对象s.B(),而不是proxy0.B(),所以对B的切入无效,因为压根就没用代理对象去调用;
解决方案就是把service的A方法中对B的调用改成代理对象的调用,怎么获取代理对象呢,AopContext.currentProxy()使用ThreadLocal保存了代理对象,因此((Service) AopContext.currentProxy()).B()就能解决。
去除外部事务,因为事务只控制保存部分,提交部门实际业务下,不需要控制事务: