什么是事务?
事务是对数据库进行一组操作时的最小单位(不可再分割),这一组操作作为一个整体向数据库进行提交,要么都执行,要么都不执行。
事务的四大特性(ACID)
- 原子性(Atomicity):
事务是对数据库操作的最小执行单位,不允许再分割;原子性保证了事务要么都执行,要么都不执行。 - 一致性(Consistency):
执行事务前后,数据要保持一致。保证了多个事务对同一个数据的读取结果相同。 - 隔离性(Isolation):
多个事务同时访问数据库时,事务之间相互不干扰。 - 持久性(Durability):
一个事务提交后,对数据库的改变结果是持久的,数据库产生故障也不会对其有任何的影响。
高并发时事务产生的问题
在高并发时,多个事务可能会同时操作同一个数据,在这个过程中可能会产生如下问题:
- 脏读(Dirty read):
当一个事务正在对数据库的数据进行了修改时,而修改还没有提交到数据库中,此时另外一个事务刚好在读取这个数据,然后使用这个数据。但是这个数据是还没有进行提交的原始数据,那么另外一个事务读到的这个数据就是“脏数据”。 - 丢失修改(Lost to modify):
当一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也对这个数据进行了修改。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 - 不可重复读(Unrepeatableread):
当一个事务反复读取一组数据时。此时这个事务还没有结束,同时另一个事务也访问该数据并对数据进行了修改。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。 - 幻读(Phantom read):
当一个事务读取了几行数据后,此时另一个事务插入了一些数据。在随后的读取中,第一个事务可能会读取到第二个事务插入的数据,但是这些数据在之前并不存在。就像产生了幻觉一样,所以称为幻读。
不可重复读与幻读的异同:
不可重复读与幻读都是读取了被修改的数据,但是不可重复读重点在于读取了被修改数据字段,而幻读重点在于读取了新的行数据。
事务的隔离级别:
SQL 标准定义了四个隔离级别:
- READ-UNCOMMITTED(读取未提交):
最低的隔离级别,允许读取未提交的数据变更,可能会导致脏读、幻读或不可重复读。 - READ-COMMITTED(读取已提交):
允许读取已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。 - REPEATABLE-READ(可重复读):
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 - SERIALIZABLE(可串行化):
最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ-UNCOMMITTED | √ | √ | √ |
READ-COMMITTED | × | √ | √ |
REPEATABLE-READ | × | × | √ |
SERIALIZABLE | × | × | × |