1、MVCC
- InnoDB的事务隔离级别已提交读和可重复读的底层实现原理:
MVCC
(多版本并发控制)–》并发的读取方式:快照读 - InnoDB提供了2种读取操作: 锁定读和非锁定读
- 锁定读就是读取的时候加锁了(S锁或者X锁)
- 非锁定读就是读取的时候没有加锁,指的就是MVCC提供的快照读–》依赖底层的undo log回滚日志。
事务日志: undo log
回滚日志 和 redo log
重做日志
ACID,A:原子性,C:一致性,I:隔离性,D:持久性
- ACD:(依靠 事务日志 保证的)
- I:(依靠 锁+MVCC 保证的)
undo log回滚日志的主要作用:
- 事务发生错误时回滚rollback ,回滚日志(数据在更新的时候,把改之前的数据存下来在回滚日志中,目的是为了事务万一出错回滚了或者我们手动回滚的时候,能够把最初的数据在回滚日志中找到)
- 提供了MVCC的非锁定读(快照读)—》undo log的原理
2、undo log回滚日志
undo log:回滚日志, 保存了事务发生之前的数据的一个版本,用于事务执行时的回滚操作,同时也是实现多版本并发控制(MVCC)下读操作的关键技术。
DB_TRX_ID
:事务IDDB_ROLL_PTR
:回滚指针
在MVCC下,针对表的所有记录,除了我们能看到的book_id,book_name等存放书籍信息的一张表,如下:
它还会给这张表添加额外的字段如下:
我们看到额外添加了3个字段。
1、DB_ROW_ID
- DB_ROW_ID和MVCC的关系不大,这个是你在创建表的时候,如果没有加主键列,那么InnoDB就给你增加的主键列id,为了区分每一行记录,通过这个id作为主键创建索引树,在B+树的叶子节点上存放一行一行的数据,因为InnoDB的数据和索引是存放在一起的,如果你没有设置主键,它会帮你设置主键。
2、DB_TRX_ID
- DB_TRX_ID(事务ID) (1002, 1001, 1000),我们在之前经常登录两个窗口session,然后各输入begin;这个意思就是在两个窗口上各开启一个事务,事务开启的请求最终会发到MySQL server上,MySQL server为每1个事务都会分配一个全局的,不冲突的事务ID。(InnoDB存储引擎分配的,因为它才支持事务)
- 那也就是说,当我这个事务1修改数据的时候,DB_TRX_ID放的就是事务1的ID,同一个事务对这个数据不断改来改去,这个事务ID是不会改变的。
3、DB_ROLL_PTR
- DB_ROLL_PTR(回滚指针)
- 我们看到,存放的是地址,这个地址表示的是一个数据的内存的位置,看起来是一个链表,上图中的这个橙色表是最后的成品,那么这个表是怎么变来的呢?
最初的时候表是这样的:
假设现在有一个事务来更改这条数据了。
这个事务把book_name给更改了。
改成了这个:
此时数据涉及到修改了,修改的数据存放在当前这个位置,那修改之前的数据存放在哪里?存放在undo log中!
假设最初是 最初给这条数据赋值的事务的ID是1000,回滚指针是空
现在另一个事务要对数据进行修改:
对这条数据修改的事务的ID是1020,它的DB_ROLL_PTR指针就指向修改之前的数据(undo log,是写在缓存中的,提高效率)
假设现在1000这个事务又把book_name给更改了
此时之前的这2条数据就是老数据了,都到undo log里面了
- MVCC会给我们创建的表增加2个列,一个是事务ID,一个是指向修改前的数据的指针
- 修改之前的数据都是放在undo log回滚日志当中。
- 当前数据中是哪个事务ID改的就写哪个事务ID号,DB_ROLL_PTR指针把当前数据和旧数据串成1个链表。从当前行的DB_ROLL_PTR可以访问到旧数据,进行回滚是理所当然的。
- 绿色数据表示当前行的最新修改的数据,是事务1002修改的,从指针DB_ROLL_PTR可以找到undo log找到上次修改数据的是事务1001,从事务1001的数据的DB_ROLL_PTR还可以找到上上次的数据是事务1000修改的。以此类推。
举例讲解
我们现在对id=7这条记录进行更改。
- 在MVCC机制下,对这张表增加2列。修改当前数据的事务ID和指向undo log的指针。
我们把id=7的age改为16。如下图所示:
假如我们增加了1行新数据。
因为新的数据就没有老数据,如下图所示:
- 回滚的时候发现是空,就知道是insert增加的数据。回滚的时候执行delete就把这条数据删除了。
- 如果我们对这条新数据进行修改了,那么这些数据就都跑到undo log中了!
如下图所示:
MVCC多版本并发控制
- MVCC是多版本并发控制(Multi-Version Concurrency Control,简称MVCC),是MySQL中基于乐观锁理论实现隔离级别的方式,用于实现已提交读和可重复读隔离级别的实现,也经常称为多版本数据库。
- MVCC机制会生成一个数据请求时间点的一致性数据快照 (Snapshot), 并用这个快照来提供一定级别 (语句级或事务级) 的一致性读取。从用户的角度来看,好象是数据库可以提供同一数据的多个版本(系统版本号和事务版本号)。