zoukankan      html  css  js  c++  java
  • 【问题排查】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();
    }
     

  • 相关阅读:
    ExtJs-学习篇(1)
    js中的Ajax经典示例
    软件工程开发流程
    Maven和Ajax
    搭建SSH框架
    拦截器
    OGNL
    Struts 2配置详解
    Struts 2入门
    HQL连接查询和注解
  • 原文地址:https://www.cnblogs.com/gossip/p/14812889.html
Copyright © 2011-2022 走看看