package org.springframework.transaction.annotation;
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
private final int value;
private Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
一,事务隔离级别
在Java Spring框架中,事务隔离级别是一个关键概念,它定义了事务在并发执行时相互之间的隔离程度。Spring支持多种事务隔离级别,这些级别与标准SQL事务隔离级别一致,主要目的是为了避免多个事务并发执行时可能出现的脏读、不可重复读和幻读等问题。以下是Spring框架中支持的事务隔离级别及其特点:
1. DEFAULT(默认)
- 描述:使用底层数据库的默认隔离级别。通常情况下,数据库的默认隔离级别是READ_COMMITTED(如Oracle)或REPEATABLE_READ(如MySQL)。
- 特点:默认情况下,使用此隔离级别即可,除非有特殊需求。
2. READ_UNCOMMITTED(读取未提交数据)
- 描述:最低的隔离级别,允许一个事务读取另一个事务未提交的数据。
- 优点:性能最好,因为几乎没有隔离。
- 缺点:数据一致性最差,容易产生数据错误,可能导致脏读、不可重复读和幻读问题。
- 适用场景:几乎不推荐使用,除非对数据一致性要求极低且追求最高性能。
3. READ_COMMITTED(读取已提交数据)
- 描述:保证一个事务只能读取到已经提交的数据。
- 优点:避免了脏读问题,性能相对较好。
- 缺点:可能会出现不可重复读和幻读问题。
- 适用场景:这是大多数数据库的默认隔离级别,通常情况下是比较合理的选择。
4. REPEATABLE_READ(可重复读取)
- 描述:保证一个事务在多次读取同一数据时,能够得到一致的结果。即使在读取期间有其他事务修改了数据,该事务也只能看到它最开始读取的值。
- 优点:避免了脏读和不可重复读问题,确保了同一事务内多次读取数据的一致性。
- 缺点:仍然可能出现幻读问题,性能较READ_COMMITTED略差。
- 适用场景:适合需要防止不可重复读的情况。
5. SERIALIZABLE(可串行化)
- 描述:最高的隔离级别,确保并发事务之间不会发生任何并发问题。它通过强制事务串行执行来避免脏读、不可重复读和幻读问题。
- 优点:提供了最严格的数据一致性保障。
- 缺点:性能最差,可能导致大量锁竞争,降低并发性能。
- 适用场景:在数据一致性要求极高且并发量较低的场景下使用。
二、适用场景
-
READ_UNCOMMITTED
- 适用场景:通常用于不太关注数据一致性的场景,如日志收集等。
- 注意事项:风险较高,不适合大多数业务场景,因为可能导致数据不一致。
-
READ_COMMITTED
- 适用场景:适合需要避免脏读,但可以接受不可重复读和幻读的场景。
- 注意事项:风险适中,适合大多数在线事务处理系统。
-
REPEATABLE_READ
- 适用场景:适用于需要确保数据一致性,防止不可重复读的场景,例如财务应用。
- 注意事项:风险较低,适合需要严格数据一致性的应用场景。
-
SERIALIZABLE
- 适用场景:适用于需要最高数据一致性和完整性的场景,但性能开销大。
- 注意事项:严重影响性能,因为会锁住很多数据,导致并发度降低。适用于金融系统和其他需要严格数据完整性的系统。
三、设置方式
在Spring中,可以通过@Transactional注解来设置事务的隔离级别。例如
@Service
public class MyService {
@Transactional(isolation = Isolation.READ_COMMITTED)
public void method1() {
// 业务逻辑
}
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void method2() {
// 业务逻辑
}
}
四、事务的四大特性
1. 原子性(Atomicity)
事务包含的所有数据库操作要么全部成功,要不全部失败回滚。
2. 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。一致性规定事务提交前后只存在两个状态,提交前的状态和提交后的状态,绝对不会出现中间的状态。最典型的例子就是银行转账,A和B之间互相转账,账面加起来总和5000元,无论A和B之间怎么转,转几次,成功与否,事务结束后A和B账面总和还是5000元。
3. 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
4. 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
五,事务并发时存在的问题
1. 脏读(Dirty Read)
脏数据所指的就是未提交的数据,而脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。比如,一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。
2. 不可重复读(Non-repeatable Read)
一个事务先后读取同一条记录,而事务在两次读取之间该数据被其它事务所修改,则两次读取的数据不同,我们称之为不可重复读。例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发生了不可重复读。
不可重复读和脏读的区别:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是在同一事务内读取了前一事务提交的数据,即前一次读到的数据是另一个事务提交前,后一次读到的数据是提交后的。
3. 幻读(Phantom Read)
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样。
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。