MySQL InnoDB MVCC的理解

时间:2020-05-26 01:28:53   收藏:0   阅读:83

参考了以下博文:

https://www.imooc.com/article/17290

https://baijiahao.baidu.com/s?id=1629409989970483292&wfr=spider&for=pc

MVCC(Mutil-Version Concurrency Control),就是多版本并发控制,实现对数据库的并发访问。

单纯加锁:InnoDB是支持行锁的,这也是防止在多线程的情况下造成数据冲突。但是这种方式时低效的,因为当事务A在对某行数据进行修改的时候加的是排他锁,那么事务B要是想读这条数据就会被堵塞,只能等这行数据的锁被释放(就是事务A提交的时候),才能对数据进行访问。但是数据库一般读操作要大于写操作,而有一个写所有的读都会被堵塞,这是很低效的。

解决办法:MVCCMySQL的实现依赖undo log+read view+排他锁(复制到redo log时用到排他锁)

. 两个关键

?

. 如何进行判断

在读某行的时候需要对事务id进行判断,从而决定这行数据:可以返回当结果 / 不可以的话遍历版本链的下一条记录再进行判断

  1. 如果该行记录的事务id小于当前under viewmin_id,就可以直接返回这条结果(可见的)
  2. 如果该行记录的事务id大于当前under viewmax_id,就是不可见的(这种情况对应的都是在不可重复读下,一个事务A创建之后,另一个事务B再创建,并对这行数据进行修改,当事务A再读这行数据的时候,这行数据记录的trx_id就大于事务A read viewmax_id,所以这条数据数据是不可见的,只能遍历这条数据的旧版本找合适的<因为不可重复读要求当一个事务开启后,别的事务不能再对这行数据进行修改,所以事务B对这行数据的修改,对于事务A是不可见的>
  3. 如果该行记录的事务id(命名为trx_id_row)对于当前under viewmin_id<=trx_id_row<=max_id,那么就遍历under view的事务id集合,如果有trx_id_row,说明trx_id_row这个事务还没有提交,这个版本就是不可见的,如果没有说明已经提交了,就可以访问
  4. 如果该行记录的事务id等于创建under view的事务id,说明读取的是自己本事务修改过的记录,是可以访问的

?

. 不同隔离情况下的under review

  1. 已提交读:每个事务创建的时候都会创建一个under review,并且每次sql语句执行之前都会删掉旧的under review创建一个新的under review
  2. 可重复读:在创建事务的时候创建under review,并且这个under review为全局的,里面的值一直不会发生变化

?

. 举个栗子

事务50和60分别对小明这行进行了修改并提交了

1. 此时有一个事务id为100的事务,修改了name,使得的name等于小明2,但是事务还没提交。则此时的版本链是

技术图片

那此时另一个事务发起了select 语句要查询id为1的记录,那此时生成的ReadView 列表只有[100]。那就去版本链去找了,首先肯定找最近的一条,发现trx_id是100,也就是name为小明2的那条记录,发现在列表内,所以不能访问。

这时候就通过指针继续找下一条,name为小明1的记录,发现trx_id是60,小于列表中的最小id,所以可以访问,直接访问结果为小明1

2.?这时候我们把事务id为100的事务提交了,并且新建了一个事务id为110也修改id为1的记录,并且不提交事务,则此时的版本链是

技术图片

这时候之前那个select事务又执行了一次查询,要查询id为1的记录。

关键地方来了:

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!