Spring事务五个特性:
- 事务传播机制
- 事务隔离机制
- 只读
- 事务超时
- 回滚规则
事务传播机制
- REQUIRED
Spring默认的传播机制,能满足绝大部分业务需求。如果外层有事务,则当前事务加入到外层事务,一块提交,一块回滚。如果外层没有事务,则新建一个事务执行。 - REQUIRES_NEW
该事务传播机制是每次都会新开启一个事务。如果外层有事务,则将外层事务挂起,开启一个新事务,当当前事务执行完毕,再恢复外层事务的执行。如果外层没有事务,则新建一个事务执行。 - SUPPORTS
如果外层有事务,则加入外层事务,一块提交,一块回滚。如果外层没有事务,则直接使用非事务方式执行。 - NOT_SUPPORTED
该传播机制始终以非事务方式执行。如果外层有事务,则将外层事务挂起,当前代码以非事务方式执行,执行完毕后,再恢复外层事务。 - NEVER
如果外层有事务就抛出异常。如果外层没有事务,当前代码以非事务方式执行。 - MANDATORY
如果外层有事务,则当前事务加入到外层事务,一块提交,一块回滚。如果外层没有事务,则抛出异常。 - NESTED
如果外层有事务,则开启一个子事务,外层事务为父事务,父事务发生异常回滚时,子事务也会回滚;子事务发生异常回滚时,父事务可以捕获子事务的异常,从而保证父事务不发生回滚。由此可以看出NESTED事务是不完全独立的。如果外层没有事务,则新建一个事务执行。
可以在@Transaction
注解中定义propagation
,指定当前事务的传播级别:
@Transactional(propagation = Propagation.NEVER)
事务隔离机制
问题:
- 脏读
- 不可重复读
- 幻读
- DEFAULT
默认使用后端数据库本身使用的隔离级别。 - READ_UNCOMMITTED
读未提交,可能导致脏读、不可重复读或幻读。 - READ_COMMITTED
读已提交(Oracle 默认级别),可防止脏读,但不可重复读和幻读仍可能会发生。 - REPEATABLE_READ
可重复读(MYSQL默认级别),对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变,可防止脏读和不可重复读,但幻读仍可能发生。 - SERIALIZABLE
序列化,确保不发生脏读、不可重复读和幻读,通常是通过完全锁定当前事务所涉及的数据表来完成的,牺牲了性能。
可以在@Transaction
注解中定义isolation
,指定当前事务的隔离级别:
@Transactional(isolation = Isolation.READ_COMMITTED)
只读
在将spring事务设置成只读后,当前只读事务就不能进行写的操作,否则将抛出异常。
可以在@Transaction
注解中定义readOnly
,指定当前事务为只读:
@Transactional(readOnly = true)
事务超时
spring事务默认超时时间是-1,即没有超时时间限制。
可以在@Transaction
注解中定义timeout
,单位是秒,指定超时时间:
@Transactional(timeout = 60)
注:
设置一个方法的事务超时时间为60秒。当程序执行了60秒还没有跑完这个方法,且这个方法后面还有对数据库的增删改查操作,则会报事务超时错误,事务回滚。当程序执行了60秒还没有跑完这个方法,且这个方法后面没有对数据库的增删改查操作,则不会报事务超时错误。
参考文章:spring事务中的超时时间很多人都不理解
回滚规则
spring事务默认回滚策略:RuntimeException
、Error
。
可以在@Transaction
注解中定义noRollbackFor
和rollbackFor
,指定某种异常是否回滚:
@Transactional(rollbackFor = Exception.class)
@Transactional(noRollbackFor = RuntimeException.class)
参考文章:有关Spring事务,看这一篇就足够了