spring事务的传播机制和隔离级别

96 阅读5分钟

事务是逻辑处理原子性的保证手段,通过使用事务控制,可以极大的避免出现逻辑处理失败导致的脏数据等问题。

事务最重要的两个特性,是事务的传播级别和数据隔离级别。传播级别定义的是事务的控制范围,事务隔离级别定义的是事务在数据库读写方面的控制范围。

事务的传播级别

PROPAGATION_REQUIRED

spring默认的事务传播级别:如果上下文中已经存在事务,则加入到事务中执行;如果当前上下文不存在事务,则新建一个事务执行.这个级别通常能够满足大多数的业务场景.

PROPAGATION_SUPPORTS

supports支持:如果上下文中已经存在事务,则加入到事务中执行;如果没有事务,则使用非事务的方式执行.也就是说并非所有加入到transactionTemplate.execute中的代码都会有事务支持. 这个通常是用来处理那些并非原子性的非核心业务逻辑操作.应用场景较少.

PROPAGATION_MANDATORY

该级别要求上下文中必须存在事务,否则就会抛出异常.使用这种方式的传播级别是有效的控制上下文调用代码遗漏添加事务的保证手段.比如一段代码不能单独调用执行,但是一旦被调用,就必须有事务包含的情况,就可以使用该级别.

PROPAGATION_REQUIRES_NEW

new:每次都新建一个事务执行,并且同时将上下文中的事务挂起,等待当前事务执行完后,上下文的事务恢复执行.

PROPAGATION_NOT_SUPPORTED

不支持事务:上下文中如果存在事务则挂起事务,执行当前逻辑,结束后恢复上下文的事务执行. 这个级别可以将事务尽可能的缩小.我们知道一个事务越大,它的风险就越大.所以在事务执行的时候尽可能的缩小事务的范围.比如一段代码中,包含一个循环1000次的非核心业务逻辑操作.如果这段代码放到事务中,就会造成事务非常大,导致出现一些考虑不到的异常情况,这时这个事务级别的传播级别就派上用场了.

PROPAGATION_NEVER

PROPAGATION_NEVER传播级别要求上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行.

PROPAGATION_NESTED

嵌套级别事务。该传播级别特征是,如果上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务.

嵌套是子事务套在父事务中执行,子事务是父事务的一部分,在进入子事务之前,父事务建立一个回滚点,叫save point,然后执行子事务,这个子事务的执行也算是父事务的一部分,然后子事务执行结束,父事务继续执行.看几个问题:

子事务回滚

如果子事务回滚,父事务会回到进入子事务前的save point,然后开始尝试其它事务或业务逻辑,父事务的其它操作不会受到子事务的影响,也不会回滚.

父事务回滚

如果父事务回滚,子事务也会跟着回滚.因为子事务是父事务的一部分,在父事务结束之前子事务是不会提交的.

嵌套事务的提交

因为子事务是父事务的一部分,所以嵌套事务的提交时子事务先提交,然后再提交父事务.

数据隔离级别

Serializable

最严格的级别,事务串行执行,资源消耗最大

REPEATABLE READ

保证一个事务不会修改已经由另一个事务修改但未提交或回滚的数据.避免了脏读和不可重复读的情况,但是带来了性能的损失

READ COMMITTED

大部分主流数据库默认的事务级别.保证一个事物不会读取到另一个并行事务已修改但未提交的数据.避免了脏读.

Read Uncommitted

保证读取过程中不会读到非法数据.

概念说明

脏读

当一个事务正在访问数据,并且对数据进行了修改,而这个事务还没提交到数据库中.这时另外一个事务访问了这个数据,因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据就是脏数据,依据脏数据所做的操作可能是不正确的.

不可重复读

在一个事务内,多次读同一个数据.在这个事务还没结束时,另外一个事务也访问了该数据. 那么在第一个事务的两次读取数据之间,由于第二个事务的修改,导致读到的数据可能是不一样的.这样就产生了在一个事务中两次读到的数据不一样,因此称之为不可重复读. 例如:一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档. 当编辑人员第二次读取文档时,文档已更改. 原始读取不可重复。如果 只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。

幻读

指当事务不是独立执行时发生的一种现象. 例如第一个事务对表中的数据进行了修改,这种修改涉及到表中的全部数据.同时第二个事务对该表插入了一条数据. 那么操作第一个事务的人会发现表中还有没有修改的数据.就好象 发生了幻觉一样. 例如:一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中. 如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题.