事务
什么是事务
在计算机科学中,事务(Transaction)是一个操作序列,它们作为一个整体被执行,以保证数据的完整性和一致性。如果事务中的所有操作都成功完成,那么事务将被提交,更改将被永久保存。如果事务中的任何一个操作失败,整个事务将被回滚,就像没有任何操作被执行过一样。
以下是事务的一些关键特性,通常被称为ACID四大特性:
-
原子性(Atomicity):
事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个点。
-
一致性(Consistency):
事务必须保证数据库从一个一致的状态转移到另一个一致的状态。
-
隔离性(Isolation):
并发执行的事务之间不会互相影响。
-
持久性(Durability):
一旦事务提交,它对数据库的改变就是永久性的,即使系统发生故障也不会丢失。
注意:只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的。
事务的隔离级别
SQL 标准定义了四个隔离级别:
-
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
-
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
-
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
-
SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
事务的并发问题
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)。并发虽然是必须的,但可能会导致一下的问题。
-
脏读(Dirty read): 指的是A事务读取到B事务尚未提交的数据,“脏数据”指的是未提交的数据。
-
不可重复读(Unrepeatableread): 指的是A事务使用相同条件多次读取同一数据,得到的结果不一致。
-
幻读(Phantom read): 指的是A事务使用相同条件多次读取某一批数据,得到的记录条数不一致。幻读与不可重复读类似,区别在于不可重复读的重点是修改,幻读的重点在于新增或者删除。
-
丢失更改:指的是A、B事务先后更改同一数据,先修改的结果就被丢失了。
不可重复度和幻读区别:
例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。
例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读。
隔离级别与并发问题的关系
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
未提交读(Read uncommitted) | ✅ | ✅ | ✅ |
已提交读(Read committed) | ❌ | ✅ | ✅ |
可重复读(Repeatable read) | ❌ | ❌ | ✅ |
可串行化(Serializable ) | ❌ | ❌ | ❌ |
常见的事务类型
-
分布式事务管理的应用程序,可以使用 JTA 。Spring 提供了 JtaTransactionManager 来支持 JTA(Java Transaction API)。