暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MYSQL MVCC 实现机理 与 知识漏洞要补

AustinDatabases 2019-09-03
1559


说来惭愧,被友人问了一些关于MYSQL 的问题,虽然算不上对答如流,但也算是沉稳应对。唯独折在 MVCC 中MYSQL INNODB 是如何实现的问题上,回答错误扣10分。本着知错能改,有漏洞要补的,精神。还是的把MVCC 以及MYSQL 怎么实现MVCC 的事情重新的学习一遍。


MVCC 首先是为并发而产生的(MVCC  multi version Concurrency control),而因为要并发事务,使用了2PL 2段锁,下面画一个图来看看两段锁


2 Phase lock 包含两个区段,扩展和收缩,而在实际当中这个而两个阶段其实可以通过commit  rollback来进行区分,在此之前都是 Growing 阶段,在这之后都就属于shrink 了。



而基于两段锁的原理,就产生最初的两种锁  S  X 锁,S 锁用于读,在记录被加载S 锁的时候,是不能进行相关记录行的数据更新的,但可以添加其他S锁进行数据的读取, X 锁则是在记录更新时,不能有其他X 锁,或S锁在此记录上加锁。

而这样的锁的设置,就引起一些争论点,使用这样的方式的数据库的性能低下。那如何能在此理论下,提出一个能提升系统性能的方法,就变得重要了。

开发人员提出了,多版本控制的方法来降低由于锁的问题,而产生的性能问题,这就是 MVCC 的由来。


对于多版本的控制,来说在设计的时候回会在每行记录中增加三个隐藏的字段, DB_TRX_ID  用来记录这一行的的事务 当前使用它的事务ID , DB_ROLL_PTR 则是记录这条记录与UNDO 空间记录之间的关系,好在记录回滚的时候,映射出回滚段与记录之间的关系。

其中 DB_TRX_ID 是保留事务最新的 ID 号,而 DB_ROLL_PTR 则是指向UNDO LOG 中修改行中被修改前的信息。(这不就有两个版本了,1 新的修改的记录, 2 没被修改的记录)多版本控制仅仅在  RR , RC 两个MVCC 中进行支持。

在InnoDB多版本控制方案中,当您使用SQL语句删除一行时,它不会立即从数据库中物理删除。InnoDB只有在丢弃为删除而编写的update undo日志记录时,才会物理地删除相应的行及其索引记录。这个删除操作称为清除,它非常快,通常使用与执行删除操作的SQL语句相同的时间顺序。


从中我们可以推出,UNDO LOG 一定是要在事务commit前进行的,

1  数据提出修改

2  将数据修改前的信息刷新到 UNDO LOG 

3  更新要更新的数据

4  将UNDO LOG 的信息落到磁盘中

5  BINLOG 记录

6  事务提交

注:这里未涉及 REDO LOG  以及各种BUFFER 的讨论


在多版本控制中,聚集索引和secondary INDEX 之间的数据更新是不同的,更新secondary索引列时,将删除旧的辅助索引记录,插入新记录,并最终清除删除标记的记录。二级索引记录被删除或二级索引页被update的事务更新时,InnoDB在聚集索引中查找数据库记录。在聚集索引中,检查记录的DB_TRX_ID,如果在读取事务启动后修改了记录,则从undo日志中检索记录的正确版本。


所以在多版本控制中,UNDO LOG 起到不可替代的作用,在事务未提交,中进行数据的读取是,UNDO LOG 将提供当时的记录信息,而表中的行中的隐藏字段将对多版本的控制是一个关键的设计。


同时如果一次进行的事务比较大,例如UPDATE 就要占用更大的UNDO LOG 的空间,如果更新的事务的大小,频次过多,还可能引起整体的数据性能低下,所以控制事务的大小对整体的系统的性能是至关重要的。


而要说 MVCC 最大的初衷,个人认为

1   读不影响写

2   写不影响读

是MVCC 最要实现的功能。


在学习的过程中,一般都是由整体延展性的学习知识,可能由于各种问题,某些关键性的东西忘记,或根本就没有注意,或自以为自己会了,所以有个人能不停的问你一些问题,帮你做扫描,这是好事,谢谢那位友人。


最后修改时间:2019-11-22 17:37:39
文章转载自AustinDatabases,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论