基于django的电子商务网站设计,wordpress 中文cms主题,郑州网页设计公司有哪些,wordpress页面数据库文章目录 简介事务版本号行记录的隐藏列Undo LogRead View的工作流程总结参考文献 简介
在不同的DBMS里#xff0c;MVCC的实现机制是不同的。本节我们会以InnoDB举例#xff0c;讲解InnoDB里MVCC的实现机制。
我们需要掌握这么几个概念#xff1a;
事务版本号行记录的隐藏… 文章目录 简介事务版本号行记录的隐藏列Undo LogRead View的工作流程总结参考文献 简介
在不同的DBMS里MVCC的实现机制是不同的。本节我们会以InnoDB举例讲解InnoDB里MVCC的实现机制。
我们需要掌握这么几个概念
事务版本号行记录的隐藏列Undo LogRead View
事务版本号
什么是事务版本号
每开启一个事务我们就会从数据库中获得一个事务ID这个ID就是事务的版本号。它是自增长的通过这个ID我们就可以判断不同事务的时间顺序。
行记录的隐藏列
什么是行记录的隐藏列
InnoDB的叶子段里存储了数据页数据页中保存了行记录而在行记录里有一些比较重要的隐藏字段。
如图 db_row_id隐藏的行ID用来生成默认的聚集索引。如果我们在创建数据表的时候没有指定聚集索引那么InnoDB就会使用这个隐藏的行ID来创建聚集索引。借以提升查找效率。
db_trx_id操作这个数据的事务ID其实就是最后一个对该数据进行插入或者更新的事务ID。
db_roll_ptr回滚指针指向这个记录的Undo Log信息。
Undo Log
什么是Undo Log
InnoDB把行记录快照保存在了Undo Log里。
如图所示 由上图可见回滚指针其实是将这个数据行的所有快照记录通过链表结构串联了起来。每个快照记录都保有了操作的事务ID。
当想要找历史快照的时候就遍历回滚指针查找即可。
Read View的工作流程
read view是如何工作的
这个比较复杂。
首先它有什么作用我们前面讲过Undo Log里保存了很多历史快照那么对一个事务来讲它应该查询哪个历史快照呢
这时候就需要用到Read View了其解决了行的可见性问题。
一个事务在开启时会创建属于自己的Read View这里面保存了事务开启时所有活跃还没有提交的事务列表。换个角度理解这里面保存的其实是不应该让当前事务看到的其他所有事务。还没提交的事务的内容原则上是不应该被别人看到的
Read View里有几个重要的属性
trx_ids其他活跃事务的ID集合low_limit_idtrx_ids中最大的事务IDup_limit_idtrx_ids中最小的事务IDcreator_trx_id创建这个Read View的事务ID。
如图所示下面是一个trx_ids集合其中最大事务为trx8最小事务是trx2当前事务是creator_trx_id。 如果当前事务想要读取某一行记录而这一行记录保存的最后修改事务ID是trx_id_line那么有这么几种情况
如果trx_id_line up_limit_id即当前最小活跃事务就说明在这些活跃事务创建之前这个行记录就已经被提交了那么这个行记录对该事务应该是可见的。
如果trx_id_line low_limit_id说明该行记录在这些活跃的事务创建之后才创建这个行记录对当前事务应该不可见。
如果 up_limit_id trx_id_line low_limit_id说明trx_id_line 这个事务可能在当前事务创建的时候还处于活跃状态所以我们可以去trx_ids里去遍历。如果找到的话说明这个事务还没提交那么这条记录应该不可见没找到的话说明事务已经提交了该行记录可见。
原理简单的说就是在creator_trx_id这个事务创建的时候如果trx_id_line这个事务是活跃的那么它对应的行记录是不可见的如果不是活跃的那么对应的行记录就是可见的。这个其实就是避免脏读的概念。只不过是通过事务ID大小比较的方式来实现的。
最后我们串一串完整的流程当查询一条记录的时候系统到底是如何通过多版本并发控制技术来找到它的:
获取当前事务自己的版本号即事务ID获取自己的Read View查询得到的行记录数据与Read View中的活跃事务版本号进行比较如果行记录符合Read View的规则即行记录对当前事务可见那就直接读这条行记录如果行记录不符合Read View的规则即行记录对当前事务不可见原因见上那就去Undo Log里获取该行记录符合情况的历史快照最后返回符合规则的数据。
因此在InnoDB中MVCC是通过Undo Log Read View来进行数据读取Undo Log保存了数据的历史快照而Read View帮助我们判断当前最新版本的数据是否可见不可见那就去Undo Log里取历史。
总结
MVCC是通过乐观锁思想来保证事务的隔离。
MVCC 的核心就是 Undo Log Read View“MV”就是通过 Undo Log 来保存数据的历史版本实现多版本的管理“CC”是通过 Read View 来实现管理通过 Read View 原则来决定数据是否显示。
需要注意针对不同的隔离级别Read View 的生成策略不同。或者说根据Read View的生成策略不同MVCC得以实现不同的隔离级别。
当隔离级别是读已提交时一个事务中每次select查询都会获取一次Read View如果每次获取到的Read View不同就会产生不可重复读或者幻读的情况。
当隔离级别是可重复读的时候一个事务只在第一次select 的时候获取一次Read View之后的select都是对这个Read View的复用解决了不可重复读的问题。同时在可重复读的隔离级别下InnoDB会采用MVCC Next-Key锁的机制来避免幻读问题。
那当隔离级别是读未提交时就不合适用MVCC来控制了。因为根本就不需要用版本控制了大家都直接读最新的行记录就可以了。
InnoDB中有三种行级锁
记录锁对单个行记录添加锁间隙锁Gap Locking锁住一个范围但不包括记录本身。采用间隙锁可以防止幻读的产生应该是锁住范围不让范围增加或者减少但是对记录的update应该还是可以的估计防止不了不可重复读。Next-Key锁锁住一个范围同时锁定范围本身相当于是间隙锁记录锁。
在读已提交的情况下InnoDB采用的是记录锁在可重复读的隔离级别下InnoDB会采用Next-Key锁的机制。
参考文献
31丨为什么大部分RDBMS都会支持MVCC