什么是事务?
保证业务(一系列对数据库增删改操作)的原子性,原子:表示不可分割,要么存在要么不存在,是一个最小单位。那么事务就是一批操作视为一个原子操作,要么成功要么失败。
事务的ACID特性
- A(Atomic):原子性,当前事务操作是一个最小单位,不可拆分。
- C(Consistency):一致性,不论事务执行成功还是失败,数据库中的数据始终是一致的。
- I(Isolation):隔离性,多个事务操作同一笔数据时,各个事务处于一个被隔离的空间,是独立的。
- D(Durability):持久性,一旦事务提交,修改的数据是永久性的。
事务的隔离级别
- 脏读:一个事务读到另一个事务未提交的更新数据,而另一个事务最终回滚,我们称这类数据为脏数据,这种现象称为脏读。
- 不可重复读:事务T1多次读取同一数据,而事务多T2次对这一数据进行更新,导致T1每次读取的数据不一样。
- 幻读:事务T1执行一次查询,然后事务T2插入或者删除一条数据,恰好T2这条操作的数据刚好满足T1的检索条件。这时事务T1再执行一次查询,此时得到的数据和第一次查询的数据不一致,这种现象称为幻读。
数据库事务隔离级别(4种),Spring除了有数据库的4种还有一种默认。 - ISOLATION_DEFAULT:默认使用数据库的事务隔离级别。
- ISOLATION_READ_UNCOMMITTED:读未提交,可以读到未提交的数据,该级别可能会出现脏读、不可重复读、幻读等问题。
- ISOLATION_READ_COMMITTED:读已提交,只能读到已提交的数据,该级别可以有效避免脏读,但可能会出现不可重复读、幻读的问题。Oracle,SQL Server默认使用此级别。
- ISOLATION_REPEATABLE_READ:可重复读,该方式专门为不可重复读这一现象定制,改级别可以避免脏读和不可重复读,但可能会出现幻读。MySQL默认使用此级别。
- ISOLATION_SERIALIZABLE:可串行化,将事务按照顺序执行,即多个事务不能同时执行,该级别为最高级别,性能上有较大影响,但能避免脏读、不可重复读、幻读等问题。
注意:如果想在某个业务方法中可以读取到未提交的数据,可以使用@Transactional(isolation = Isolation.READ_UNCOMMITTED)
来设置事务的隔离级别。
Spring事务的传播性
事务的传播特性的产生,当多个业务嵌套调用时事务的执行策略,是Spring利用其底层资源特性来实现的。
Spring为我们提供了以下其中事务的传播性
- PROPAGATION_REQUIRED:必须使用事务,如果当前业务存在一个事务,则加入,如果不存在,则创建一个事务,默认使用此种方式。
- PROPAGATION_SUPPORTS:支持事务,如果父业务存在事务,则加入,如果不存在,则不使用事务。
- PROPAGATION_MANDATORY:强制使用事务,如果父业务不存在事务,则抛出异常。
- PROPAGATION_REQUIRES_NEW:如果当前存在事务,则挂起该事务新建一个事务,如果不存在事务,则同PROPAGATION_REQUIRED
- PROPAGATION_NOT_SUPPORTED:不支持事务,如果当前存在事务,则挂起,自己不使用事务去执行数据库操作。
- PROPAGATION_NEVER:不使用事务,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:嵌套事务,如果当前存在事务,则开启一个子事务,但是父事务可以控制子事务是否提交和回滚,子事务的回滚父事务可以选择回滚或者提交。如果当前不存在事务,则同PROPAGATION_REQUIRED