IOTXING

记录技术学习之路

0%

spring事务(1)

Spring中的事务,主要有以下几个参数

  • value:事务名称
  • transactionManager:事务管理器
  • propagation:传播行为
  • isolation:隔离级别
  • timeout:超时时间,如果在超时时间内事务没有提交,则事务就会被终止(此处会有坑)
  • readOnly:是否只读事务(需要参考所用的数据源是否支持,如mysql支持只读事务)
  • rollbackFor:何时回滚
  • noRollbackFor:在遇到某些异常时,不回滚

传播行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 加入当前的事务,如果当前没有事务,则创建一个新的事务
* spring里面的默认事务隔离级别
*/
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

/**
* 加入当前存在的事务中,如果没有,就以非事务的形式执行
*/
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

/**
* 加入当前事务,如果当前事务不存在,则会报错
*/
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

/**
* 创建一个新的事务,如果当前有事务存在,则把当前事务挂起
*/
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

/**
*以非事务的形式执行,如果当前存在事务,会暂停当前的事务
*/
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

/**
* 以非事务的形式执行,如果当前存在事务,则报错
* Analogous to EJB transaction attribute of the same name.
*/
NEVER(TransactionDefinition.PROPAGATION_NEVER),

/**
* 如果当前事务存在,以嵌套事务的形式执行代码,跟PROPAGATION_REQUIRED有些类型,只是不会加入上一个事务,
* 而是以嵌套的形式存在,在嵌套事务开启的时候,上层事务会存储一个savepoint,如果嵌套事务发生了回滚,上层会
* 恢复到savepoint,当全部提交的时候,该事务才会被提交
*/
NESTED(TransactionDefinition.PROPAGATION_NESTED);

隔离级别

Spring中的隔离级别大致跟mysql的隔离级别一样,为四种,Spring中还多一个缺省值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 默认值,默认使用数据库中定义的事务隔离级别
*/
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),

/**
*读未提交,该隔离级别可能会出现以下问题,脏读,不可重复读以及幻读。该隔离级别在允许别的事务能够立马堵到已经
*做出修改的数据,而不考虑是否提交,如果被修改的数据最终没有提交,就会导致脏读。
*/
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),

/**
*读已提交,能够避免出现脏读的情况,只会读取已经提交后的数据,但是还是会可能导致不可重复读以及幻读,
*不可重复读:当存在并发事务时,如果a已经提交了事务,b读取并进行了修改但是还没有提交,此时a又开始了一个事
*务,并读取了数据,此时b提交事务,就是导致a在提交事务的时候,值已经被b修改了。
*/
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),

/**
*mysql的默认隔离级别是可重复读
*可重复读,能够避免脏读,不可重复读的情况,但是还是会出现幻读的情况。该情况会避免事务读取一个未提交的行数
*据变更,并且会阻止当并发事务出现,事务读取一行数据,b事务修改该数据,然后a读取到不同的值的情况
*/
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),

/**
*串行读,会对所有涉及到的行都进行加锁,避免别的事务进行写操作,因此在提交之前,第一个事务每次重新读取数据的
*时候,都不会发生变化,避免了幻读的出现。幻读是指a事务在读取数据的时候,b往其中插入了一条数据并且提交了,
*在a重新读取的时候,多了一条没有读过的数据出来
*/
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);

超时时间

一般如果不设置的话,默认使用的是数据源的事务超时设置时间。如果数据源也没有设置超时时间的话,就很容易会出现坑。详情参考 事务超时时间导致的坑

最好还是设置一个超时时间,并且把耗时长的行为,移到事务外面

RollBackFor

设置需要回滚的情况,如RuntimeException或者自定义的异常类

NoRollbackFor

设置不需要回滚的情况,例如有些异常是我们已知的,并且不想让事务回滚,就可以使用该参数,指定出现该异常时,不回滚