事务与锁介绍(3)

1.前文

前面介绍了数据库锁的作用和mvcc实现的隔离级别,这里探讨一下mysql中mvcc的实现
前文:
https://blog.csdn.net/qq_24516549/article/details/89374174
https://blog.csdn.net/qq_24516549/article/details/89405983

2.高性能mysql里介绍的mvcc实现

事务与锁介绍(3)_第1张图片

3.innodb的mvcc实现

行记录有以下隐藏字段:

  • db_row_id,行ID,用来生成默认聚簇索引(聚簇索引,保存的数据在物理磁盘中按顺序保存,这样相关数据保存在一起,提高查询速度)
  • db_trx_id,事务ID,新开始一个事务时生成,实例内全局唯一
  • db_roll_ptr,undo log指针,指向对应记录当前的undo log
  • deleted_bit,删除标记位,删除时设置

3.1 undo log

undo log用于行记录回滚,同时用于实现MVCC

事务与锁介绍(3)_第2张图片

具体的mvcc操作:

update

行记录数据写入undo log,事务的回滚操作就需要undo log
更新行记录数据,当前事务ID写入db_trx_id,undo log指针写入db_roll_ptr

delete

和update一样,只增加deleted_bit设置

insert

生成undo log
插入行记录数据,当前事务ID写入db_trx_id, db_roll_ptr为空

这样设计使得读操作很简单,性能很好,并且也能保证只会读到符合标准的行,不足之处是每行记录都需要额外的储存空间,需要做更多的行检查工作,以及额外的维护工作

DB_ROLL_PTR用来指定undolog里的行号,同时undolog里的该行也会有上一次的DB_ROLL_PTR来指定上一次修改,这看起来像是这一行有多个版本,他们像链表一样被连接

3.2 read view

mvcc还需要判断当前事务对记录的可读性,通过read_view判断

在InnoDB中,创建一个新事务的时候,InnoDB会将当前系统中的活跃事务列表(trx_sys->trx_list)创建一个副本(read view),副本中保存的是系统当前不应该被本事务看到的其他事务id列表。当用户在这个事务中要读取该行记录的时候,InnoDB会将该行当前的版本号与该read view进行比较。
具体的算法如下:

设该行的当前事务id为trx_id,read view中最早的事务id为trx_id_min, 最迟的事务id为trx_id_max。

如果trx_id< trx_id_min的话,那么表明该行记录所在的事务已经在本次新事务创建之前就提交了,所以该行记录的当前值是可见的。
如果trx_id>trx_id_max的话,那么表明该行记录所在的事务在本次新事务创建之后才开启,所以该行记录的当前值不可见。
如果trx_id_min <= trx_id <= trx_id_max, 那么表明该行记录所在事务在本次新事务创建的时候处于活动状态,从trx_id_min到trx_id_max进行遍历,如果trx_id等于他们之中的某个事务id的话,那么不可见。
从该行记录的DB_ROLL_PTR指针所指向的回滚段中取出最新的undo-log的版本号的数据,将该可见行的值返回。
需要注意的是,新建事务(当前事务)与正在内存中commit 的事务不在活跃事务链表中。

你可能感兴趣的:(高性能Mysql)