SQL标准定义了四个隔离级别如下:
READ UNCOMMITTED(未提交读):允许读取尚未提交的变更数据。READ COMMITTED(已提交读):允许读取事务已经提交的数据。REPEATABLE READ(可重复读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务所修改。SERIALIZABLE(可串行化):最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰。| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ UNCOMMITTED | 可能 | 可能 | 可能 |
| READ COMMITTED | 不可能 | 可能 | 可能 |
| REPEATABLE READ | 不可能 | 不可能 | 可能 |
| SERIALIZABLE | 不可能 | 不可能 | 不可能 |
说明:
READ UNCOMMITTED 隔离级别下,可能发生脏读、不可重复读和幻读现象;READ COMMITTED 隔离级别下,可能发生不可重复读和幻读现象,但是不可能发生脏读现象;REPEATABLE READ 隔离级别下,可能发生幻读现象,但不可能发生脏读和不可重复读现象;SERIALIZABLE 隔离级别下,上述现象都不可能发生。因为脏写现象对数据一致性影响太严重了,所以无论哪种隔离级别,都不允许脏写的情况发生。
MySQL InnoDB 存储引擎默认的隔离级别是 REPEATABLE READ(可重复读)。我们可以通过 SELECT @@tx_isolation; 命令来查看,MySQL 8.0之后该命令改为 SELECT @@transaction_isolation;
mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ |
+-------------------------+
1 row in set (0.00 sec)
MySQL 在 REPEATABLE READ 隔离级别下,是可以解决幻读问题发生的,主要有下面两种情况:
Next-Key Lock(Record Lock + Gap Lock)。