目录
MVCC
MVCC是什么?
全称是 Multiversion Concurrency Control,中文是多版本并发控制技术。通过数据行的多个版本管理来实现数据库的并发控制,简单来说它的思想就是保存数据的历史版本。读取数据的时候不需要加锁也可以保证事务的隔离效果(乐观锁思想)
MVCC解决了什么问题?
1,读写之间阻塞的问题,通过 MVCC 可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并发处理能力。
2,降低了死锁的概率。乐观锁,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。
3,解决一致性读(快照读、不加锁读),当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。
MVCC 是如何实现的?
MVCC 没有正式的标准,所以在不同的 DBMS 中,MVCC 的实现方式可能是不同的
MVCC是多版本并发控制技术,那么InnoDB 是如何存储记录的多个版本的呢?
事务版本号
每一个事务,都分配一个自增长的 ID,确定了事务的时间顺序
行记录的隐藏列
叶子节点段的数据页中保存了行记录,行记录中有一些隐藏字段
- db_row_id:隐藏的行 ID,用来生成默认聚集索引。如果创建数据表的时候没有指定聚集索引,这时 InnoDB 就会用这个隐藏 ID 来创建聚集索引。采用聚集索引的方式可以提升数据的查找效率。
- db_trx_id:操作这个数据的事务 ID,也就是最后一个对该数据进行插入或更新的事务 ID。
- db_roll_ptr:回滚指针,也就是指向这个记录的 Undo Log 信息。
Undo Log
InnoDB 将行记录快照保存在了 Undo Log 里,在回滚段位置:
回滚指针将数据行的所有快照记录都通过链表的结构串联了起来,每个快照的记录都保存了当时操作这个数据的事务 ID。如果想要找历史快照,就可以通过遍历回滚指针的方式进行查找。
多个事务对同一个行记录进行更新会产生多个历史快照,历史快照保存在 Undo Log 里。如果一个事务想要查询这个行记录,需要读取哪个版本的行记录呢?
Read View
Read View是一条当前未提交的事务列表, 保存了不应该让某事务看到的其他的事务 ID 列表;也就是说,当一个事务读取某条行记录时,Read View决定了此行记录(可能正被其他事务使用或创建时间晚于所有活跃事务)能否被读取到。
当查询一条记录的时候,系统如何通过多版本并发控制技术找到它:
- 首先获取事务自己的版本号,也就是事务 ID;
- 获取 Read View;
- 查询得到的数据,然后与 Read View 中的事务版本号进行比较;
- 如果不符合 ReadView 规则,就需要从 Undo Log 中获取历史快照;
- 最后返回符合规则的数据。
MVCC 是通过 Undo Log + Read View 进行数据读取,Undo Log 保存了历史快照,而 Read View 规则判断当前版本的数据是否可见