什么是事务?
要么都成功要么都失败,不可分隔的数据库操作序列,事务是最小的执行单位,不能分割
事务的四大特性ACID
- 原子性:要么全部完成,要么全部失败;事务是最小的执行单位,不可分割
- 一致性:执行事务前的数据保持一致,多个事务对同一个数据的读取结果是一致的
- 隔离性:并非不是访问数据时,一个用户的事务不受其他事务的影响
- 持久性:事务被提交以后,对数据的修改是持久性的
事务的隔离级别
为了达到事务的四大特性,定义了四种事务的隔离级别
- 已读未提交(read-uncommitted):允许读取尚未提交的数据变更;
- 读取已提交(read-committed):允许读取事务已经提交的数据;阻止脏读,可能幻读不可重复读
- 可重复读(repeatable-read):多次读取数据一致,除非数据或者事务已经被修改;可能出现幻读
- 可串行(serializable):最高的隔离级别,事务逐个执行,符合四大特性,避免了其他的问题
如果不考虑事务的隔离性,会出现以下问题:
- 脏读:指一个线程中的事务读取到了另外一个线程中未提交的数据。
- 不可重复读(虚读):指一个线程中的事务读取到了另外一个线程中提交的update的数据。
-
幻读:指一个线程中的事务读取到了另外一个线程中提交的insert的数据。
mysql默认的是:可重复读(repeatable-read)
oracle默认的是:读取已提交(read-committed)
事务的传播机制
- REQUIRED:如果有事务则加入事务;如果没有事务则创建新的事务(默认值)注:当两个方法传播机制都是REQUIRED时,一旦发生回滚,两个方法都会回滚
- NOT_SUPPORTED:Spring不为当前方法开启事务,相当于没有事务
@Transactional(propagation=Propagation.NOT_SUPPORTED) - REQUIRED_NEW : 不管是否存在事务,都创建一个新的事务,原来的方法挂起来,新的方法执行完毕以后,继续执行老的方法
@Transactional(propagation=Propagation.REQUIRED_NEW)
注:当delete方法传播机制为REQUIRED_NEW,会开启一个新的事务,并且单独提交方法,所以save方法回滚不影响delete方法事务的提交 - MANDATORY:必须在一个已有的事务中执行,否则报错
@Transactional(propagation=Propagation.MANDATORY) - NEVER;必须在一个没有的事务中执行,否则报错
@Transactional(propagation=Propagation.NEVER) - SUPPORTS:如果其他bean调用了这个方法时,其他bean声明了事务,就用这个事务,没有声明,那就不用事务
- NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作注:当save方法为required时,delete方法为nested时,delete方法开启一个嵌套事务;当save方法回滚时,delete方法也会回滚;delete回滚不影响save方法的提交
事务的隔离级别与锁的关系
- read-uncommitted级别下,读取数据不需要加共享锁,不会跟被修改数据的排它锁冲突
- read-committed级别下,读取数据的时候加上共享锁,语句执行完以后释放锁
- repeatable-read级别下,读取操作要加上共享锁,事务完成以后才能释放锁
- serializable级别下,锁定整个范围的键,一直持有锁,直到事务完成
网友评论