mysql中mvcc机制和BufferPool详解

MVCC:

多版本并发控制(Multi-Version Concurrency Control),是多事务之间并发访问数据带来的问题;数据库的写写操作是互斥加锁阻塞的,读和写的操作就是利用mvcc来达到并发访问同一条数据的目的。
MySQL读已提交和可重复读隔离级别实现了mvcc机制;

Mvcc的机制是依赖undo日志版本链、read view一致性视图;
每一行记录会有两个隐藏的字段:
1.DB_TRX_ID:事务id,记录创建或修改这条记录最后的事物id;
2.DB_ROLL_PTR:回滚指针,指向这条记录的上个版本;

Undo log有两种:
1.Insert undo log:事务insert插入新数据产生的,只在事务回滚时需要,在 事务提交后被立即丢弃;
2.Update undo log:事务在update和delete时产生的,不仅在事务回滚时需要,在快照度时也需要,所以不能随便删除,只有在快照读和回滚时不涉及该日志,才会被purge线程统一清除;

purge线程:
为了实现InnoDB的MVCC机制,更新或者删除操作都只是设置一下老记录的deleted_bit,并不真正将过时的记录删除。
为了节省磁盘空间,InnoDB有专门的purge线程来清理deleted_bit为true的记录。为了不影响MVCC的正常工作,purge线程自己也维护了一个read view(这个read view相当于系统中最老活跃事务的read view);如果某个记录的deleted_bit为true,并且DB_TRX_ID相对于purge线程的read view可见,那么这条记录一定是可以被安全清除的。

在这里插入图片描述
1、事务id为20的先对id=1的行的name字段进行修改;(之前的版本数据没有画出来,是这个undo log的首位数据)
2、事务id分别为40、30、20按时间有序的对user表id=1的行进行修改,在每个事务提交之前id=1的行是加行锁的,只有上一个事务进行提交之后下一个事务才能开启。
3、每个版本的DB_ROLL_PTR:回滚指针指向上一个版本,这样形成了undo log版本链。

Read view(读视图)
在这里插入图片描述
在可重复读隔离级别下,当开启事务,当执行任何查询时会生成 read view读视图,在视图在事务提交之前都不会发生变化,但是在读已提交的隔离级别执行,每次执行查询sql时会重新生成一个读视图。
Read view包含以下三个属性:
1、trx_list:在生成read view那一刻系统中正在活跃的事务id,即所有未提交的事务id;
2、up_limit_id: trx_list中最小的事务id
3、low_limit_id:在read view生成时系统尚未分配的下一个事务id,也就是当时存在最大的事务id+1;

利用undo log和read view工作流程:
先拿到undo log中首位版本的事务id,和read view进行比较,如果符合条件则显示当前版本的数据,如果不符合则利用DB_ROLL_PTR回滚指针找到上一个版本的事务id和read view进行比较,查看是否满足条件,以此类推,知道取到符合条件的版本数据。
如何利用事务id和read view进行比较的呢?
(1)、先用DB_TRX_ID和up_limit_id进行比较,如果小于up_limit_id,则说明是已提交的事务,对当前事务是可见的,或者DB_TRX_ID等于当前事务id,说明当前版本的数据是当前事务修改的,是可见的。如果大于等于,则进入一步判断;
(2)、判断DB_TRX_ID是否大于等于low_limit_id,如果是,代表在read view生产的时刻,当前事务还未进行提交,所以对当前事务不可见的。如果小于则进入下一个判断;
(3)、判断DB_TRX_ID是否在活跃事务之中,trx_list.contains(DB_TRX_ID), 如果是在活跃事务之中,说明在生成read view那一刻事务还未提交是不可见的,如果不在,在说明在read view生成之前已经提交,是可见的;
以下是Read view判断的源码图片:
在这里插入图片描述

innodb下的buffer pool机制:

Buffer pool是数据库内存中的一个重要内存组件,里面缓存了磁盘上的真实数据,对数据库的增删改操作,就是对这个缓存中的数据执行的。

在这里插入图片描述
commit; --> write XID to redo. --> write data to Binlog. --> write filename,postsion of binlog to redo. --> commited.

有两个疑问点:

  • Redo log的作用:当buffer pool的修改的数据还有写入磁盘时,服务器宕机了,那么可以利用redo log恢复buffer pool中的数据。

为什么不直接把修改的数据写入磁盘,而是等到写完redo log后再写入磁盘:
因为redo log是顺序写,修改的数据写入磁盘是随机写(找到指定位置进行写入,要写入指定的数据页),顺序写(追写在文件的最后)的效率比随机写的效率高很多,提高了并发能力;
Buffer pool中存在的是一页一页的数据,称之为缓存页,对于每个缓存页都有一个单独的描述信息,包含一下一些描述信息:这个数据页所属的表空间、数据页的编号、这个缓存页在buffer pool中的地址等等一些信息,通过描述信息才能找到文件中指定写入的位置,所以随机写比较慢;

如何设置buffer pool的大小:
数据库的curd都是直接操作buffer pool的,建议设置机器内存的60%左右。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值