MySQL 的事务隔离性是数据库事务管理的重要特性之一,它定义了在并发环境中,不同事务间的互相影响。事务隔离性决定了一个事务执行过程中,其他事务对它的操作是否可见,以及在并发环境下如何避免数据不一致的情况。
MySQL 支持的事务隔离级别有四种,分别是:
- READ UNCOMMITTED(读取未提交)
- READ COMMITTED(读取已提交)
- REPEATABLE READ(可重复读)
- SERIALIZABLE(可串行化)
READ UNCOMMITTED(读取未提交)
-
描述:在这个隔离级别下,事务可以读取其他事务尚未提交的数据,也就是说,事务可以看到"脏数据"(Dirty Read)。这种隔离级别允许事务读取其他事务未提交的修改。
-
问题:
- 脏读(Dirty Read):一个事务读取到另一个事务未提交的数据,而后者的事务如果回滚,这时前者读取的数据就不再有效,造成数据的不一致。
- 不可重复读(Non-repeatable Read):如果一个事务在执行过程中多次查询同一数据,而该数据在查询过程中被其他事务修改,导致查询结果不一致。
- 幻读(Phantom Read):当一个事务在查询时,另一个事务插入、更新或删除了数据,导致前一个事务查询的结果集发生变化。
-
适用场景:该级别适用于对数据一致性要求不高的场景,性能优先的情况。
READ COMMITTED(读取已提交)
-
描述:在该隔离级别下,事务只能读取已经提交的数据。这意味着一个事务只能看到其他事务提交后的数据,不能看到未提交的脏数据。每次查询时都会读取到最新已提交的数据。
-
问题:
- 不可重复读(Non-repeatable Read):一个事务如果执行两次相同的查询操作,可能会读到不同的结果,因为其他事务在中间提交了修改。
- 幻读(Phantom Read):类似于 “可重复读” 级别的问题,其他事务在查询期间可能会插入或删除数据,导致查询的结果发生变化。
-
适用场景:适用于对事务一致性要求相对较高,但对性能要求较高的场景。常见的 OLTP 系统中,很多时候会采用这个级别。
REPEATABLE READ(可重复读)
-
描述:在此隔离级别下,事务在执行期间会看到相同的数据。即一个事务执行时,它对同一数据的查询结果在事务结束之前都是一致的,避免了不可重复读的问题。
-
特点:
- 避免脏读和不可重复读:保证事务内部的一致性,事务执行期间读到的数据是事务开始时的快照,不受其他事务影响。
- 幻读问题:虽然该级别可以解决脏读和不可重复读,但仍然可能发生幻读(即其他事务插入新的记录,导致当前事务查询结果集变化)。MySQL InnoDB 存储引擎通过使用 Next-Key Lock 来减少幻读的发生。
-
适用场景:适合大部分需要强一致性的应用,特别是金融等要求较高事务一致性的应用。
SERIALIZABLE(可串行化)
-
描述:该隔离级别是最严格的,事务执行时会强制其他事务等待。为了避免并发冲突,SERIALIZABLE 隔离级别会使事务像串行执行一样,确保事务之间完全没有重叠。这会锁定读取的数据行或数据集,防止其他事务插入、更新或删除这些数据。
-
问题:
- 性能开销大:因为每个事务都必须等待前一个事务完成后才能开始,导致并发性大大降低,性能最差。
- 避免脏读、不可重复读和幻读:这是该隔离级别的优点,它避免了所有类型的读一致性问题。
-
适用场景:适用于极端情况下,要求数据一致性和隔离性非常高的场景,比如在金融行业的关键操作中。
隔离级别 | 脏读 | 不可重复读 | 幻读 | 锁定方式 |
---|---|---|---|---|
READ UNCOMMITTED | 允许 | 允许 | 允许 | 无 |
READ COMMITTED | 不允许 | 允许 | 允许 | 行级锁 |
REPEATABLE READ | 不允许 | 不允许 | 允许 | 行级锁、Next-Key Lock |
SERIALIZABLE | 不允许 | 不允许 | 不允许 | 全表锁/行锁 |
总结
- READ UNCOMMITTED:最弱的隔离级别,可能发生脏读、不可重复读和幻读,性能最优,但不适合需要高一致性的场景。
- READ COMMITTED:解决了脏读问题,但可能发生不可重复读和幻读,适合大多数场景。
- REPEATABLE READ:提供了更强的保证,避免了脏读和不可重复读,但仍然可能发生幻读,适合需要高一致性的事务。
- SERIALIZABLE:最强的隔离级别,完全避免了所有一致性问题,但性能最差,适合对事务一致性要求极高的场景。