【问题排查】select for upate 引起的问题

 
 
一. 代码说明
  1. M2方法的预期作用是根据id值(主键)加行锁,整个方法放在事务中执行
  2. M1方法调用M2方法
复制代码
public class C
{
    public void M1()
    {
        this.M2();
    }
    
    @Transactional
    public void M2()
    {
        String sql="select * from t1 where id=1 for update";
        executeSql(sql);
        
        // 其它的一些事务操作
    }
}
复制代码

 

二. 问题
1. M2方法事务未生效,并排除异常
select * from t1 where id=1 for update --readonly

 

三. 原因分析
  1. 数据库是一主多从结构,读写分离
  2. 方法上加@Transactional注解,不管是查询还是增删改,都可以保证走主库,可是异常提示"readonly",说明select语句走了从库
  3. M1和M2在同一个类C中,this.M2()语句并没有使用类C在容器中的代理对象,而是使用原生对象调用M2方法,故@Transactional注解未生效
  4. 由于@Transactional未生效,又因为"select * from t1 where id=1 for update"是读语句,会主动走从库,从库又是只读的,所以会抛出readonly异常
 
四. 解决方案
  1. 单独的类中调用:在单独的类中使用类C的代理对象调用M2方法
  2. 类C中操作:从IOC容器获取代理对象
public void M1() {
    C c = SpringUtils.getBean(C.class);
    c.M2();
}

 

  1. 类C中操作:在类中定义代理对象并使用
@Autowired
private C c1;

public void M1() {

    c1.M2();
}

 

 

posted @     阅读(102)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2012-05-26 AspnetMvc实现无刷新省市联动功能
2012-05-26 使用Moq模拟AspnetMvc中的Request.Form
点击右上角即可分享
微信分享提示