精华内容
下载资源
问答
  • JDBC事务回滚失败

    2021-02-18 13:13:34
    JDBC事务回滚失败 在使用Connection 对象connection完成开启事务,提交事务,回滚事务的时候 由于mysql数据库的引擎使用的为MyISAM导致事务回滚失败 将mysql数据库引擎改为InnoDB,即可。

    JDBC事务回滚失败

    在使用Connection 对象connection完成开启事务,提交事务,回滚事务的时候
    由于mysql数据库的引擎使用的为MyISAM导致事务回滚失败
    将mysql数据库引擎改为InnoDB,即可。
    在这里插入图片描述

    展开全文
  • 事务回滚失败

    2018-09-28 10:50:46
    按照上面的代码自己写事务测试,发现回滚失败,刚开始以为是自动提交,查看了一下自动提交状态: show variables like 'autocommit'\G 果然状态时开启的,于是我设置成关闭状态: set autocommit=off; ...
    mysql> use RUNOOB;
    Database changed
    mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb; # 创建数据表
    Query OK, 0 rows affected (0.04 sec)
    mysql> select * from runoob_transaction_test;
    Empty set (0.01 sec)
    mysql> begin; # 开始事务
    Query OK, 0 rows affected (0.00 sec)
    mysql> insert into runoob_transaction_test value(5);
    Query OK, 1 rows affected (0.01 sec)
    mysql> insert into runoob_transaction_test value(6);
    Query OK, 1 rows affected (0.00 sec)
    mysql> commit; # 提交事务
    Query OK, 0 rows affected (0.01 sec)
    mysql> select * from runoob_transaction_test;
    +------+
    | id |
    +------+
    | 5 |
    | 6 |
    +------+
    2 rows in set (0.01 sec)
    mysql> begin; # 开始事务
    Query OK, 0 rows affected (0.00 sec)
    mysql> insert into runoob_transaction_test values(7);
    Query OK, 1 rows affected (0.00 sec)
    mysql> rollback; # 回滚
    Query OK, 0 rows affected (0.00 sec)
    mysql> select * from runoob_transaction_test; # 因为回滚所以数据没有插入
    +------+
    | id |
    +------+
    | 5 |
    | 6 |
    +------+
    2 rows in set (0.01 sec)
    mysql>

    按照上面的代码自己写事务测试,发现回滚失败,刚开始以为是自动提交,查看了一下自动提交状态:

    show variables like 'autocommit'\G

    果然状态时开启的,于是我设置成关闭状态:

    set autocommit=off;

    测试了一番还是不行,然后就各种找原因,后面突然想到表类型是MYISAM的,后面把表类型改成InnoDB,就可以了

    MYISAM不支持事务

    展开全文
  • 主要介绍了java事务回滚失败问题分析,具有一定借鉴价值,需要的朋友可以参考下
  • 假如一个用户去修改资料是有事务的,用户修改失败,但是事务回滚失败,可以手动回滚吗?
  • Spring事务回滚失败的原因 Spring事务管理机制的实现原理-动态代理 在spring中实现动态代理就两种方式,一是使用JDK实现InvocationHandler接口,二是使用CGlib实现MethodInterceptor接口 这里简单说一下两者的区别...

    Spring事务回滚失败的原因

    Spring事务管理机制的实现原理-动态代理

    在spring中实现动态代理就两种方式,一是使用JDK实现InvocationHandler接口,二是使用CGlib实现MethodInterceptor接口

    这里简单说一下两者的区别:

    1.代理的对象要求不同:

    JDK是通过代理类实现了的接口去控制类的,换句话说JDK是代理接口的

    CGlib适用范围更广,能代理没有通过接口定义业务方法的类,即直接代理类的

    2.两者实现的技术不同:

    JDK采用反射机制调用委托代理类方法

    CGlib通过字节码层面截取类的所有方法,采用类似索引的方式直接调用委托类方法

    基于JDK的实现,这个代理类适用于任何接口的实现

    public class TxHandler implements InvocationHandler {
    private Object originalObject;
    public Object bind(Object obj) {
     this.originalObject = obj;
     return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    }
    
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
     Object result = null;
     if (!method.getName().startsWith("save")) {
      UserTransaction tx = null;
      try {
       tx = (UserTransaction) (new InitialContext().lookup("java/tx"));
       result = method.invoke(originalObject, args);
       tx.commit();
      } catch (Exception ex) {
       if (null != tx) {
        try {
         tx.rollback();
        } catch (Exception e) {
       }
      }
     }
    } else {
     result = method.invoke(originalObject, args);
    }
    return result;
    }
    }
    

    先看这段代码

    return Proxy.newProxyInstance(
     obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    

    newProxyInstance方法根据传入的接口类型(obj.getClass.getInterfaces())动态构造一个代理类实例返回,这也说明了为什么动态代理实现要求所代理的对象一定要实现一个接口,这个代理类实例在内存中是动态构造的,它实现了传入的接口列表中所包含的所有接口。

    再来分析以下代码:

    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
     ……
     result = method.invoke(originalObject, args);
     ……
     return result;
    }
    

    为什么spring的事务不用我们手动开启,因为别人在方法调用的前后就已经帮我们开启了事务,InvocationHandler.invoke方法将在被代理类的方法被调用之前触发。通过这个方法,我们可以在被代理类方法调用的前后进行一些处 理,如代码中所示,InvocationHandler.invoke方法的参数中传递了当前被调用的方法(Method),以及被调用方法的参数。同 时,可以通过method.invoke方法调用被代理类的原始方法实现。这样就可以在被代理类的方法调用前后写入任何想要进行的操作。

    Spring的事务管理机制实现的原理,就是通过这样通过对调用方法前后加一些代码操作,帮你开启事务。

    基于CGlib

    CGlib也是,只不过实现的方式不同。GClib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截所有的父类方法的调用并顺势织入横切逻辑

    相当于继承了被代理对象,然后重写了代理对象的方法,在方法逻辑前后加入开启事务的代理块,所以CGlib也是有限制的,因为继承所以它代理不了private、final、static修饰的方法

    class CgProxy implements MethodInterceptor {
        public Object intercept(Object o, Method method, Object[] objects,
                                MethodProxy methodProxy) throws Throwable {
            System.out.println("输出语句1");
    //参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法
    //引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。
            Object obj= methodProxy.invokeSuper(o,objects);
            System.out.println("输出语句2");
            return obj;
        }
    }
    

    结论:spring的AOP同时使用了这两种方式,底层会自行判断应该使用哪种

    事务回滚失败

    @Service
    public class TaskService {
    
        @Autowired
        private TaskManageDAO taskManageDAO;
    
        @Transactional
        public void test1(){
            try {        
                this.test2();//这里调用会使事务失效,两条数据都会被保存
                /*           
                原因是:JDK的动态代理。
                在SpringIoC容器中返回的调用的对象是代理对象而不是真实的对象
                只有被动态代理直接调用的才会产生事务。
                这里的this是(TaskService)真实对象而不是代理对象
                 */
                 //解决方法
                TaskService proxy =(TaskService) AopContext.currentProxy();
                proxy.test2();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        // 这个事务的意思是如果前面方法有事务存在,会将前面事务挂起,再重启一个新事务
        public void test2(){
        }
    

    最常见的就是类中的方法自调用,使用了this指针去调用了方法,这里的test1中的test2方法如果执行失败,是不会回滚的,原因就是你直接调用了方法,而不是用动态代理类去调用你的方法,spring的事务机制原理就是,开启事务部分的代码你交给了代理类去做所以你不用去主动去开启事务,现在你直接调用了方法,也没有开启事务,自然就不会回滚

    避免这种情况的方法,你可以通过 @Autowired一个代理类,通过代理类去调用,也可以用前置增强和后置增强去使用事务逻辑

    为什么AOP不能代理静态方法

    因为在Java编程规范中“静态方法是可继承但不可被重写的”。

    举个例子:A类有静态方法a(),B类继承A类,B类继承了A类的静态方法,所以B类可直接使用A类的静态方法。此时若在B类中尝试重写静态方法a(),新的静态方法a()将变成独属于B类的静态方法,而失去了原属于A类静态方法a()的继承关系。注意,静态方法是独属于当前类的,你若定义便失去了父类静态方法的继承关系,新的静态方法只与当前所属类挂钩!Spring AOP的CGLIB代理在于对父类方法的重写,而对静态方法的重写,会使其失去与父类静态方法的继承关系,违背了代理的核心目的,因此CGLIB直接排除了静态方法。

    展开全文
  • springcloud分布式事务回滚失败

    千次阅读 2019-04-28 17:44:51
    springcloud分布式事务回滚失败 1.场景还原 笔者在公司最近的一个项目采用springcloud框架搭建微服务架构,这势必会引发分布式事务处理的思考,目前处理分布式主流方案tcc及消息的最终一致性;今天笔者集成github...

    springcloud分布式事务回滚失败

    1.场景还原

     笔者在公司最近的一个项目采用springcloud框架搭建微服务架构,这势必会引发分布式事务处理的思考,目前处理分布式主流方案tcc及消息的最终一致性;今天笔者集成github上较为流行的tx-lcn分布式处理框架,它是基于redis的一种补偿型处理方案
    

    2.实现方案

    ①先截图,下载该框架

    我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:从github上的starts数量来看,目前还是较多开发者采用了这种方案的,而且作者维护迭代也很及时

    ②将tx-manager微服务单独拎出来,集成在自己的项目中

    在这里插入图片描述将tx-manager中application.properties中的配置改成自己的项目配置

    ③然后涉及分布式的微服务中添加如下依赖

    <!--分布式事物-->
    <dependency>
       <groupId>com.codingapi</groupId>
       <artifactId>transaction-springcloud</artifactId>
       <version>${lcn.last.version}</version>
       <exclusions>
          <exclusion>
             <groupId>org.slf4j</groupId>
             <artifactId>*</artifactId>
          </exclusion>
       </exclusions>
    </dependency>
     
    <dependency>
       <groupId>com.codingapi</groupId>
       <artifactId>tx-plugins-db</artifactId>
       <version>${lcn.last.version}</version>
       <exclusions>
          <exclusion>
             <groupId>org.slf4j</groupId>
             <artifactId>*</artifactId>
          </exclusion>
       </exclusions>
    </dependency>
    

    ④下载tx-demo,参考链接:https://github.com/codingapi/springcloud-lcn-demo

    将其中的两个实现类复制到自己工程的service中

    在这里插入图片描述⑤开启tx-manager,在各个微服务application.yml配置tx-manager地址

    # 分布式事物
    tm:
      manager:
        url: http://localhost:8899/tx/manager/
    

    3.应用步骤

    ①分布式事务起始服务方

    @Transactional
    @TxTransaction(isStart = true)
    public int addAcount(String logId){
       int i = yiViUserAccountMapper.increaseAccount("100","71d8beff-9e70-11e7-9a60-00163e0a3457");
     
       int n =  paymentDispatchFeignClient.test(logId); //调用失败
     
       if(n == 0){
           throw new RuntimeException("服务调用失败");
       }
        return i + n;
    }
    

    ②被调用服务方

    @Override
    @Transactional
    @TxTransaction
    public int test(String logId) throws YiViException {
        int i = yiViDispatchOrderStatusLogMapper.deleteByPrimaryKey(logId);
        return i;
    }
    

    下面是错误:笔者使用分布式事务时遇到得坑,希望能解决小编得问题,服务A事务执行调用FeignConfiguration方式调用服务B事务,A事务成功回滚数据,B事务执行业务但未回滚且未发现异常错误如下:
    1.事务A回滚成功图
    在这里插入图片描述
    2.事务B未执行回滚业务图
    在这里插入图片描述4.解决问题
    先叙述下问题:因为配置文件内加载了rabbit,项目内引用了该配置文件,其中rabbit是链路追踪用于请求跟踪,导致事务A在执行回滚操作时调用事务B的初始化时未将groupId插入RequestTemplate表头内,未调用此方法代码如下:

        @Override
        public void apply(RequestTemplate requestTemplate) {
    
            TxTransactionLocal txTransactionLocal = TxTransactionLocal.current();
            String groupId = txTransactionLocal == null ? null : txTransactionLocal.getGroupId();
            int maxTimeOut = txTransactionLocal == null ? 0 : txTransactionLocal.getMaxTimeOut();
    //        this.logger.info("LCN-SpringCloud TxGroup info -> groupId:" + groupId);
    //        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
    //        HttpServletRequest request = requestAttributes == null ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
    //        Object attribute = request.getAttribute("OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE");
    //        String token = attribute == null ? null : attribute.toString();
    //        requestTemplate.header("Authorization", "Bearer " + token);
    
            logger.info("LCN-SpringCloud TxGroup info -> groupId:"+groupId+",maxTimeOut:"+maxTimeOut);
    
            if (txTransactionLocal != null) {
                requestTemplate.header("tx-group", groupId);
                requestTemplate.header("tx-maxTimeOut", String.valueOf(maxTimeOut));
            }
        }
    

    以至于事务B在执行操作时未能获取到事务组groupId而导致事务B未能回滚。解决办法如下:

        <!--<dependency>-->
          <!--<groupId>org.springframework.cloud</groupId>-->
          <!--<artifactId>spring-cloud-starter-stream-rabbit</artifactId>-->
        <!--</dependency>-->
    

    将配置文件POM.xml注释掉rabbit。重新启动事务回滚成功。

    展开全文
  • Java开发中遇到事务回滚失败,可以考虑从以下列表中寻找原因: 数据库引擎是否支持事务(Mysql的MyIsam引擎就不支持事务) 注解所在的类是否注入spring容器中 注解所在方法是否为public修饰或者final(方法...
  • Spring中事务回滚失败的解决方案

    千次阅读 2019-10-22 20:55:37
    Spring中事务回滚失败解决方案 前言        事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)...
  • laravel事务回滚失败原因

    千次阅读 2019-02-23 16:00:26
    我是一个laravel初学者,然后今天尝试写了一个事务,然后发现回滚失败了 ,找不到原因,后来发现mysql表数据要实现回滚功能必须要在选项里有个 引擎需要设置为innodb ...
  • mybatis事务回滚失败

    千次阅读 2018-11-14 15:45:48
    今天遇到了一个尴尬的问题,在使用mybatis的时候发现事务回滚不了,然后查找了一下资料才知道是mysql引擎的问题: mysql有几种引擎,当使用InnoDB的时候,才可以进行事务处理 案列如下: userMapper.xml &lt;?...
  • laravel事务回滚失败

    2019-09-28 01:22:54
    1. DB::begin...//回滚  DB::commit();//提交 2 查看MySQL数据表是否为InnoDB表 3 查看开启事务的是否为对应数据库 DB::connection('对应的数据库名')->beginTransaction(); DB::connection...
  • @Autowired注入的不是代理对象,导致事务回滚失败(@Transactional无效) https://www.guitu18.com/post/2019/10/30/56.html
  • 在常规使用@transactional注解时,如果碰到不生效问题,要首先想到如下几个问题:  1. 如果是有关数据库操作,首先要查看牵涉到的表使用的引擎是什么引擎,要知道使用"MYISAM"数据库引擎是不... 如果事务回滚失败还要...
  • tp5 事务回滚失败

    2021-03-30 14:37:30
    不使用同一条连接的数据是无法正常回滚的, tp5要注意 db的助手函数默认是强制重新连接数据库的 。 可以使用 Db::nam('order') 或者 db('order',[],false)关闭强制重新连接 3.这是我踩过的坑如果有其他问题或者...
  • java 事务回滚失败

    千次阅读 2018-01-01 16:09:46
    Spring-Java事物回滚失效处理最近在做项目中,无意间发现有个类在抛事物回滚操作,数据也正常的插入到数据库当中了,于是仔细查看看一下具体原因。 一切还是要从Java的检查型异常和非检查型异常说起。 那么...
  • Spring 中事务回滚失败

    2019-05-24 13:38:01
    原因一:在业务层捕捉异常,在业务层手工捕捉并处理了异常(try..catch)等于把异常“吃”掉了,Spring自然不知道这里有错,更不会主动去回滚数据。推荐做法是在业务层统一抛出异常,然后在控制层统一处理。 如果...
  • 今天做数据迁移, 发现事务有时候可以回滚, 有时候不可以回滚, 最后一点点调试发现中间有段修改表结构的语句, 最终导致回滚失败。 1.MySQL最常用的两个表类型: InnoDB和MyISAM。MyISAM类型的表强调的是性能,...
  • 我自己的service集成BaseService,我在service里的一个方法内插入两条数据,如果出现异常,把本次对数据库的所有操作回滚,现在问题是回滚失败,代码如下: public int saveProduct(HmProduct hmProduct) { int ...
  • 背景spring支持编程式事务管理和声明式事务管理两种方式。编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。声明式...
  • Spring 事务回滚失败

    2010-09-11 17:17:01
    applicationContext.xml中配置: 。。。。。。 (* *.impl.service.*.*(..))" /> *" propagation="REQUIRED" /> Service 文件中 package web.impl.service;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,816
精华内容 2,326
关键字:

事务回滚失败