ReadView与 MVCC操作流程
MVCC :多版本并发控制
MVCC 的实现依赖于:隐藏字段、Undo Log、Read View
ReadView内容
ReadView的规则
MVCC整体操作流程
当查询一条记录的时候,系统如何通过MVCC找到它:
- 首先
获取版本链第一条 trx_id
,也就是事务 ID; - 获取 ReadView;
- 将 trx_id 与 ReadView 中的 trx_id进行比较;
- 不符合,换下一条 trx_id
- 最后返回符合规则的数据
READ COMMITTED 隔离级别下
READ COMMITTED :每次读取数据前都生成一个ReadView!!!!!!
现在有两个 事务id 分别为 10
、 20
的事务在执行:
# Transaction 10
BEGIN;
UPDATE student SET name="李四" WHERE id=1;
UPDATE student SET name="王五" WHERE id=1;
# Transaction 20
BEGIN;
# 更新了一些别的表的记录
...
此时进行查询:
# 使用READ COMMITTED隔离级别的事务
BEGIN;
# SELECT1:Transaction 10、20未提交
SELECT * FROM student WHERE id = 1; # 得到的列name的值为'张三'
生成 ReadView视图为:
活跃事务id集合:
trx_ids=[10,20]
此时 up_limit_id :10,low_limit_id:21
表student 中id 为 1
的记录得到的版本链表
如下所示:
1、 trx_id=10,在 trx_ids 中,不符合,换下一条
2.、trx_id=10,在 trx_ids 中,不符合,换下一条
3.、trx_id=8, 8<up_limit_id,事务已提交,故:
SELECT * FROM student WHERE id = 1; # 得到的列name的值为'张三'
REPEATABLE READ隔离级别下
REPEATABLE READ: 只在 第一次进行普通SELECT操作前生成一个ReadView!!!
系统里有两个 事务id 分别为 10
、 20
的事务在执行:
# Transaction 10
BEGIN;
UPDATE student SET name="李四" WHERE id=1;
UPDATE student SET name="王五" WHERE id=1;
# Transaction 20
BEGIN;
# 更新了一些别的表的记录
...
此时进行查询:
# 使用REPEATABLE READ隔离级别的事务
BEGIN;
# SELECT1:Transaction 10、20未提交
SELECT * FROM student WHERE id = 1; # 得到的列name的值为'张三'
生成 ReadView视图为:
活跃事务id集合:
trx_ids=[10,20]
此时 up_limit_id :10,low_limit_id:21
表student 中id 为 1
的记录得到的版本链表
如下所示:
1、 trx_id=10,在 trx_ids 中,不符合,换下一条
2.、trx_id=10,在 trx_ids 中,不符合,换下一条
3.、trx_id=8, 8<up_limit_id,事务已提交,故:
SELECT * FROM student WHERE id = 1; # 得到的列name的值为'张三'
把 事务id 为 10
的事务提交一下,就像这样:
# Transaction 10
BEGIN;
UPDATE student SET name="李四" WHERE id=1;
UPDATE student SET name="王五" WHERE id=1;
COMMIT;
然后再到事务id 为 20
的事务中更新一下表 student 中 id 为 1 的记录:
# Transaction 20
BEGIN;
# 更新了一些别的表的记录
...
UPDATE student SET name="钱七" WHERE id=1;
UPDATE student SET name="宋八" WHERE id=1;
此时进行查询:
# 使用REPEATABLE READ隔离级别的事务
BEGIN;
# SELECT2:Transaction 10提交,Transaction 20未提交
SELECT * FROM student WHERE id = 1; # 得到的列name的值仍为'张三'
还是第一次select时生成的ReadView视图:
活跃事务id集合:
trx_ids=[10,20]
此时 up_limit_id :10,low_limit_id:21
表student 中id 为 1
的记录得到的版本链表
如下所示:
1、 trx_id=20,在 trx_ids 中,不符合,换下一条
2、 trx_id=20,在 trx_ids 中,不符合,换下一条
3.、trx_id=10,在 trx_ids 中,不符合,换下一条
4、trx_id=10,在 trx_ids 中,不符合,换下一条
5.、trx_id=8, 8<up_limit_id,事务已提交,故:
SELECT * FROM student WHERE id = 1; # 得到的列name的值为'张三'
解决幻读
根据 ReadView的规则分析