业内SQL标准隔离级别:
- Read Uncommitted:未提交读
- Read Committed:已提交读
- Repeatable Read:可重复读
- Serializable:可串行化
针对不同的隔离级别,并发事务执行过程中可以发生不同的现象:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read Uncommitted | 可能 | 可能 | 可能 |
Read Committed | 不可能 | 可能 | 可能 |
Repeatable Read | 不可能 | 不可能 | 可能 |
Serializable | 不可能 | 不可能 | 不可能 |
那么在MySQL是通过什么方法来实现各种隔离级别呢?
1. 对于Read Uncommitted隔离级别来说,可以读到未提交事务修改过的记录,所以直接读取记录的最新版本就可以。
2. 对于Serializable隔离级别,使用加锁的方式实现。
3. 对于使用Read Committed和Repeatable Read隔离级别,都必须保证读到已提交事务修改过的记录。核心问题就是,需要判断版本链中哪个版本是当前事务可见。在InnoDB中使用ReadView(一致性视图)实现。
首先,介绍一下InnoDB中的版本链是什么?
在聚簇索引的每条记录里,都有两个字段用于记录事务相关的信息,一是 trx_id用于记录当前操作记录的事务id,二是roll_pointer是一个指针,指向insert undo日志,该日志记录该事务的操作步骤,可以通过该日志找到记录修改前的信息。
**版本链:每对记录进行一次改动,都会记录一条undo日志,每条undo日志都有一个roll_pointer属性,通过这个属性可以将这些undo日志串成一个版本链。**如下图所示:
这里有3个未提交的活跃事务都对记录更新date1中的数据,更次更新数据后,都会将旧值放到undo日志中。版本链的头结点就是当前记录的最新值。
MVCC: 这种利用记录的版本链来控制并发事务访问相同记录的行为,这种机制称为多版本并发控制。Multi-Version Concurrency Control。