隔离级别
1、默认使用数据库的(mysql:可重复读,oracle:已提交读)
2、未提交读
线程t1(写)和线程t2(读)同时访问一条资源数据,t1正在写入数据事务还未提交的时候t2进行读取,t2能读取到t1未提交的数据,进而产生了脏读
会出现脏读、幻读、不可重复读
3、已提交读
线程t1(写)和线程t2(读)同时访问一条资源数据,t2会等t1的事务提交完再读取,这个等待的过程会产生性能损耗,但是保证了数据的有效性避免了脏读
会出现幻读、不可重复读
4、可重复读
线程t1(写)和线程t2(读)同时访问一条资源数据,t2读取这条数据的时候t1就需要等待,直到t2读取完毕后,t1才能对这个数据做些操作,避免了不可重复读
会出现幻读
5、串行化的 不会出现这3种问题
脏读:查询到另一个事务未提交的数据
幻读:查询到另一个事务insert的数据
不可重复读:查到另一个事务update的数据
@Transactional(isolation = Isolation.DEFAULT)
传播行为
PROPAGATION_REQUIRED (默认)
如果有事务就加入到这个事务中,没事务新建一个事务
PROPAGATION_SUPPORTS
有事务就加入这个事务,没事务就不开启事务了
PROPAGATION_MANDATORY
有事务就加入这个事务,没事务直接报错
PROPAGATION_REQUIRES_NEW
新建一个事务,如果已经有事务的话就先挂起来
PROPAGATION_NOT_SUPPORTED
不使用事务,如果有就挂起来
PROPAGATION_NEVER
不使用事务,如果有会报错
PROPAGATION_NESTED
如果有事务就开启一个事务嵌进去,没有的话就开启一个
解决Transactional注解不回滚
有时候我们会发现明明使用了事务标签但是事务不回滚,可能有一下几种原因:
1、检查你方法是不是public的
2、你的异常类型是不是unchecked异常
如果我想check异常也想回滚怎么办,注解上面写明异常类型即可
@Transactional(rollbackFor=Exception.class)
类似的还有norollbackFor,自定义不回滚的异常
3、数据库引擎要支持事务,如果是MySQL,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的
4、是否开启了对注解的解析
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
5、spring是否扫描到你这个包,如下是扫描到org.test下面的包
<context:component-scan base-package="org.test" ></context:component-scan>
6、检查是不是同一个类中的方法调用(如a方法调用同一个类中的b方法)
7、异常是不是被你catch住了