1、抛出的异常为非运行时异常: 导致事务发生回滚的情况是,事务当中执行的sql语句抛出了非检查异常,或者说是运行时异常或者是error。其他异常,非运行时异常抛出不会导致事务回滚。 2、try -catch 将异常捕捉: 事务当中抛出的异常,被try catch 捕捉而不继续向上抛出,事务同样不会发生回滚。 3、需要执行事务的方法发生了代理,代理没有向上抛出异常: 方法既需要执行事务,同时又被代理,而代理当中捕获异常并没有向上抛出。此时执行的顺序是 1、事务开启 2、代理方法执行 3、目标方法执行。 所以代理方法在捕获到目标方法的异常时,如果没有向上抛给事务,那么事务也不会放生回滚。 4、多线程状态下,运行同一段需要执行事务的代码: 此时,常规思维会觉得给这段代码增加 synchronized 等方式 去给代码增加锁 就可以避免,多线程下的代码冲突。 但是锁只能锁住代码,缺锁不住事务提交的这个过程。 也就是事务代码完成之后,还没有来得及提交时,这部分代码的锁已经释放开了,第二个线程已经接触到了,进而会出现异常情况。 解决方法1:给线程执行语句增加唯一的锁,如下图,只有第一个线程执行完毕 完成提交 交出锁之后,第二个线程才能获取锁。 解决方法2:在查询语句最后 增加 for update ,这样就是给查询内容增加了 记录锁和间隙锁,放到这个情景中,也就是多线程执行同一段代码的时候,select xxx for update,相同条件的sql,一定是需要第一个事务提交之后,才可以执行第二个事务的,从而解决了多线程执行同一段代码的冲突问题。 而如果不是相同的查询语句,会在自己的查询范围内增加记录锁和间隙锁,从而也可以避免其他语句在自己的范围内进行查询。