MySQL解析MVCC

什么是MVCC?

MVCC全称 multi-version concurrency control,即多版本并发控制。MVCC是一种并发控制方法,在数据库管理中,实现对数据库的并发访问。
MVCC在MySQL innodb中实现主要是为了提高数据库并发性能,使用更好的方法去处理读-写的操作,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

什么是当前读和快照读?

当前读:像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?读取的记录是最新版本,还需要保证其他事物不能修改当前记录,所以对读取的操作都进行加锁。
共享锁:共享锁又称为读锁,也就是多个事务对同一个数据共享一把锁,都能够访问数据,但是是只读不修改。
排他锁:又称写锁,就是不能与其他事务共存,一个事务获取一个数据行的排他锁,其他事务就不能获取到数据的锁。
快照读:像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本
MVCC就是为了实现读-写冲突不加锁,这个读指的是快照读,而不是当前读,其实当前读就是加锁操作。

MVCC能解决MySQL的什么问题,它的好处是什么?

数据库并发场景有三种,分别为:

  1. 读-读:不存在任何问题,也不需要并发控制

  2. 读-写:有线程安全的问题,可能会造成事务隔离问题,出现脏读,幻读,不可重复读

  3. 写-写:有线程安全问题,可能会存在更新丢失的问题。
    MVCC带来的好处是?
    多版本并发控制是一种用来解决读-写冲突的无所并发控制,也就是为了事务分配单向增长的时间,为每次修改保存一个版本,版本和事务时间戳关联,读操作只操作快照读,MVCC可以解决数据下面的问题:

  4. 在并发读写数据库时,可以做到读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能

  5. 同时解决脏读,幻读,不可重复读等事务隔离问题,解决不了数据丢失问题(因为数据未进入磁盘还在缓冲区)

MVCC的实现原理

MVCC的目的就是多版本并发控制,在数据库中的显示,就是为了解决读写冲突,它的实现原理主要是依赖记录中的三个隐式字段,undo日志,read view 来实现的。
隐式字段
每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段
DB_TRX_ID
6byte,最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID
DB_ROLL_PTR
7byte,回滚指针,指向这条记录的上一个版本(存储于rollback segment里)
DB_ROW_ID
6byte,隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引
实际还有一个删除flag隐藏字段, 既记录被更新或删除并不代表真的删除,而是删除flag变了

undo log
有两种:

  1. insert undo log
    代表事务在insert新纪录时产生的undo log,只在事务回滚时需要,并且在事务提交后可以被立即丢弃

  2. update undo log
    事务在进行uodate或delete时产生undo log,不仅在事务回滚时候需要,在快照时候也需要,
    read view(读视图)
    read view 就是事务进行快照读操作的时候生产的读视图,在该事务执行的快照读的那一刻,会生产数据库系统当前的一个快照,记录并维护系统当前活跃事务的id
    RR是如何在RC级的基础上解决不可重复读的?
    当前读和快照读在RR级别下的区别:
    表1:
    在这里插入图片描述
    表2:
    在这里插入图片描述

而在表2这里的顺序中,事务B在事务A提交后的快照读和当前读都是实时的新数据400,这是为什么呢?

这里与上表的唯一区别仅仅是表1的事务B在事务A修改金额前快照读过一次金额数据,而表2的事务B在事务A修改金额前没有进行过快照读。
所以我们知道事务中快照读的结果是非常依赖该事务首次出现快照读的地方,即某个事务中首次出现快照读的地方非常关键,它有决定该事务后续快照读结果的能力

我们这里测试的是更新,同时删除和更新也是一样的,如果事务B的快照读是在事务A操作之后进行的,事务B的快照读也是能读取到最新的数据的

RC,RR级别下的InnoDB快照读有什么不同?
正是Read View生成时机的不同,从而造成RC,RR级别下快照读的结果的不同

在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照及Read View, 将当前系统活跃的其他事务记录起来,此后在调用快照读的时候,还是使用的是同一个Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个Read View,所以对之后的修改不可见;
即RR级别下,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见
而在RC级别下的,事务中,每次快照读都会新生成一个快照和Read View, 这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因
总之在RC隔离级别下,是每个快照读都会生成并获取最新的Read View;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View。
总结
MySQL面试题 MVCC实现原理?
MVCC是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值