spring事务:
什么是事务:
事务逻辑上的一组操做,组成这组操做的各个逻辑单元,要么一块儿成功,要么一块儿失败.spring
事务特性(4种):
原子性 (atomicity):强调事务的不可分割.
一致性 (consistency):事务的执行的先后数据的完整性保持一致.
隔离性 (isolation):一个事务执行的过程当中,不该该受到其余事务的干扰
持久性(durability) :事务一旦结束,数据就持久到数据库sql
若是不考虑隔离性引起安全性问题:
脏读 :一个事务读到了另外一个事务的未提交的数据
不可重复读 :一个事务读到了另外一个事务已经提交的 update 的数据致使屡次查询结果不一致.
虚幻读 :一个事务读到了另外一个事务已经提交的 insert 的数据致使屡次查询结果不一致.数据库
解决读问题: 设置事务隔离级别(5种)
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生
已提交读 (read commited):避免脏读。可是不可重复读和虚读有可能发生
可重复读 (repeatable read) :避免脏读和不可重复读.可是虚读有可能发生.
串行化的 (serializable) :避免以上全部读问题.
Mysql 默认:可重复读
Oracle 默认:读已提交安全
read uncommited:是最低的事务隔离级别,它容许另一个事务能够看到这个事务未提交的数据。
read commited:保证一个事物提交后才能被另一个事务读取。另一个事务不能读取该事物未提交的数据。
repeatable read:这种事务隔离级别能够防止脏读,不可重复读。可是可能会出现幻象读。它除了保证一个事务不能被另一个事务读取未提交的数据以外还避免了如下状况产生(不可重复读)。
serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读以外,还避免了幻象读(避免三种)。atom
事务的传播行为
PROPAGION_XXX :事务的传播行为
* 保证同一个事务中
PROPAGATION_REQUIRED 支持当前事务,若是不存在 就新建一个(默认)
PROPAGATION_SUPPORTS 支持当前事务,若是不存在,就不使用事务
PROPAGATION_MANDATORY 支持当前事务,若是不存在,抛出异常
* 保证没有在同一个事务中
PROPAGATION_REQUIRES_NEW 若是有事务存在,挂起当前事务,建立一个新的事务
PROPAGATION_NOT_SUPPORTED 以非事务方式运行,若是有事务存在,挂起当前事务
PROPAGATION_NEVER 以非事务方式运行,若是有事务存在,抛出异常
PROPAGATION_NESTED 若是当前事务存在,则嵌套事务执行设计
1: PROPAGATION_REQUIRED
加入当前正要执行的事务不在另一个事务里,那么就起一个新的事务
好比说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么因为执行ServiceA.methodA的时候,
ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到本身已经运行在ServiceA.methodA
的事务内部,就再也不起新的事务。而假如ServiceA.methodA运行的时候发现本身没有在事务中,他就会为本身分配一个事务。
这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即便ServiceB.methodB的事务已经被
提交,可是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚事务
2: PROPAGATION_SUPPORTS
若是当前在事务中,即以事务的形式运行,若是当前再也不一个事务中,那么就以非事务的形式运行ci
3: PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。不然,他就要抛出异常it
4: PROPAGATION_REQUIRES_NEW
这个就比较绕口了。 好比咱们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成之后,
他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。由于ServiceB.methodB是新起一个事务,那么就是存在
两个不一样的事务。若是ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。若是ServiceB.methodB失败回滚,
若是他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。io
5: PROPAGATION_NOT_SUPPORTED
当前不支持事务。好比ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。
6: PROPAGATION_NEVER
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,
那么ServiceB.methodB就要抛出异常了。
7: PROPAGATION_NESTED
理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,
而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,若是父事务最后回滚,他也要回滚的。
而Nested事务的好处是他有一个savepoint。
Spring事务的隔离级别
1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务能够看到这个事务未提交的数据。
这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另一个事务读取。另一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别能够防止脏读,不可重复读。可是可能出现幻像读。
它除了保证一个事务不能读取另外一个事务未提交的数据外,还保证了避免下面的状况产生(不可重复读)。
5. ISOLATION_SERIALIZABLE 这是花费最高代价可是最可靠的事务隔离级别。事务被处理为顺序执行。
除了防止脏读,不可重复读外,还避免了幻像读。
什么是脏数据,脏读,不可重复读,幻觉读? 脏读: 指当一个事务正在访问数据,而且对数据进行了修改,而这种修改尚未提交到数据库中,这时, 另一个事务也访问这个数据,而后使用了这个数据。由于这个数据是尚未提交的数据, 那么另一 个事务读到的这个数据是脏数据,依据脏数据所作的操做多是不正确的。 不可重复读: 指在一个事务内,屡次读同一数据。在这个事务尚未结束时,另一个事务也访问该同一数据。 那么,在第一个事务中的两次读数据之间,因为第二个事务的修改,那么第一个事务两次读到的数据 多是不同的。这样就发生了在一个事务内两次读到的数据是不同的,所以称为是不可重复读。 幻觉读: 指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及 到表中的所有数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么, 之后就会发生操做第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉同样。