需要了解MVCC的原理与实现。
点击链接查看:《Mysql 进阶》 · 语雀
show variables like 'transaction%';
- +----------------------------------+-----------------+
- | Variable_name | Value |
- +----------------------------------+-----------------+
- | transaction_alloc_block_size | 8192 |
- | transaction_allow_batching | OFF |
- | transaction_isolation | REPEATABLE-READ |
- | transaction_prealloc_size | 4096 |
- | transaction_read_only | OFF |
- | transaction_write_set_extraction | XXHASH64 |
- +----------------------------------+-----------------+
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL level
- level: {
- REPEATABLE READ
- | READ COMMITTED
- | READ UNCOMMITTED
- | SERIALIZABLE
- }
select @@autocommit
- +--------------+
- | @@autocommit |
- +--------------+
- | 1 |
- +--------------+
set session transaction isolation level read committed;
start transaction; | begin;
SELECT * FROM information_schema.INNODB_TRX;
- CREATE TABLE IF NOT EXISTS `sanguo` (
- `id` int NOT NULL AUTO_INCREMENT,
- `name` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL,
- `age` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-
- INSERT INTO `sanguo` (`id`, `name`, `age`) VALUES (1, '刘备', '20');
时间 | 会话A(TRX_ID=5) | 会话B(TRX_ID=6) | 会话C(TRX_ID=7) |
T0 | 设置隔离级别为RC: | ||
T1 | 开启事务: | ||
T2 | 更新为关羽:
| ||
T3 | 更新为张飞:
| ||
T4 | 更新为赵云:
| ||
T5 | 更新为诸葛亮:
| ||
T6 | 查询记录:(刘备)
| ||
T7 | 提交事务:
| ||
T8 | 查询记录:(张飞)
| ||
T9 | 提交事务:
| ||
T10 | 查询记录:(诸葛亮)
|
我们将目光定位到T6时刻,此时的Undo Log 的状态和ReadView的情况:
根据可见性规则,T6时刻会话C查询的结果是刘备。
可见性规则:
- 如果TRX_ID小于m_low_llimit_id,则说明相对于当前事务来说,这个数据已提交,可以访问。
- TRX_ID等于当前事务的ID(m_creator_trx_id),可以访问。
- TRX_ID大于等于m_up_limit_id,说明这个数据版本是事务之后创建的,不可访问。
- 如果TRX_ID在m_low_limit_id~m_up_limit_id之间,的话,就检查TRX_ID是否在m_ids里面,在的话不能访问。
当来到T8时刻,在RC隔离级别下,每次Select都生成一条ReadView,所以此时的ReadView情况如下:
所以,当会话C再次查询记录的时候,根据可见性规则,查询的结果将是张飞。
同理,当T9时刻会话B提交事务之后,T10时刻会话C能查询记录结果为诸葛亮。
跟RC隔离级别不同的是,在第一次Select生成ReadView记录之后,后续就一直重用,不生成新的ReadView记录。
所以,在上一个案例的基础上,我们聚焦T8时刻,此时,Undo Log和ReadView的情况如下:
可以看到,RR隔离级别下,会话C继续沿用第一次生成的ReadView记录,所以,即使T7时刻会话A提交了事务,但还是能重复读取到刘备。