注:
1、事务的隔离级别和数据库并发性是成反比的,隔离级别越高,并发性越低。
2、对于不同的数据库,支持的隔离级别也不一样:Oracle只能支持读写提交和串行化,而MySQL能够支持4种,对于Oracle默认的隔离级别为读写提交,MySQL则是可重复读。
3、注解@transactional的底层实现是Spring AOP技术,而Spring AOP技术使用的是动态代理。这就意味着对于静态(static)方法和非public方法,注解@Transactional是失效的。
事物的ACID原则:
- 原子性:事务里面的操作单元不可切割,要么全部成功,要么全部失败
- 一致性:事务执行前后,业务状态和其他业务状态保持一致.
- 隔离性:一个事务执行的时候最好不要受到其他事务的影响
- 持久性:一旦事务提交或者回滚.这个状态都要持久化到数据库中
隔离级别(isolation)
- 读未提交(READ_UNCOMMITTED)
- 含义:允许一个事物读取另一个事物没提交的数据。
- 缺点:出现脏读;假设库存为2,事物a扣减库存1但还未提交,此时事物b读取a未提交的数据为1,如果此时a回滚,那么b读取到的数据就是脏数据,它的任何修改操作将会产生错误。
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
- 读已提交(READ_COMMITTED)
- 含义:一个事务只能读取另外一个事务已提交的更改数据。该级别克服了脏读。
- 缺点:不可重复读;假设库存为2,事物a扣减库存1但还未提交,此时事物b读物库存仍为2,同时a提交了,库存变为了1,那么此时b在库存为2的基础上做的修改操作将会产生错误
@Transactional(isolation = Isolation.READ_COMMITTED)
- 可重复读(REPEATABLE_READ):
- 含义:一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。克服读写提交中出现的不可重复读的现象
- 缺点:会出现幻读。
@Transactional(isolation = Isolation.REPEATABLE_READ)
注意:不可重复读和幻读的区别是:前者是指读到了已经提交的事务的更改数据(修改或删除),后者是指读到了其他已经提交事务的新增数据。
- 串行化(SERIALIZABLE)
- 含义:是数据库最高的隔离级别,它能够完全保证数据的一致性,但性能降低了。
传播行为(pragation)
- 含义:事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
- @Transactional(propagation=Propagation.REQUIRED)
- 如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
- @Transactional(propagation=Propagation.NOT_SUPPORTED)
- 容器不为这个方法开启事务
- @Transactional(propagation=Propagation.REQUIRES_NEW)
- 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
- @Transactional(propagation=Propagation.MANDATORY)
- 必须在一个已有的事务中执行,否则抛出异常
- @Transactional(propagation=Propagation.NEVER)
- 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
- @Transactional(propagation=Propagation.SUPPORTS)
- 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
- @Transactional(propagation=Propagation.NESTED)
- 在当前方法调用子方法时,如果子方法发生异常,只回滚子方法执行过的SQL,而不回滚当前方法的事务。
注:常用的传播行为主要有三种:REQUIRED 、REQUIRES_NEW、 NESTED
@Transactional注解
- 默认传播行为:REQUIRED
- 默认隔离级别:默认使用数据库的隔离级别
- 超时时间:默认使用底层事物的超时时间