• 【问题排查】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();
    }
     

  • 相关阅读:
    截除数值,分别获取数据与单位
    angularjs判断对象值是否存在
    angularjs文件上传实例
    获取Zxing.net 中所有barcodeformat
    创建QR CODE
    QR Code的容错级别
    验证QR Code版本
    Web API返回自定义数据给客户端
    理解Hive 不同组件的功能
    tcpdf中文解决方案
  • 原文地址:https://www.cnblogs.com/gossip/p/14812889.html
Copyright © 2020-2023  润新知