| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> InnoDB学习(五)之MVCC多版本并发控制 -> 正文阅读 |
|
[大数据]InnoDB学习(五)之MVCC多版本并发控制 |
MVCC多版本并发控制,是一种数据库管理系统并发控制的方法。MVCC多版本并发控制下,数据库中的数据会有多个版本,分别对应不同的事务,从而达到事务之间并发数据的隔离。MVCC最大的优势是读不加锁,读写不冲突,在读多写少场景中,读写不冲突可以大幅提升数据库的并发性能。 MVCC多版本并发控制在MYSQL中,MyISAM存储引擎使用的是表锁,InnoDB存储引擎使用的是行锁。而InnoDB的事务分为四个隔离级别,其中默认的隔离级别是可重复读,可重复读要求两个并行的事务之间数据的修改互不影响,通过添加行锁的方式虽然可以实现两个事务之间数据据的修改互不影响,但是者两个事务之间存在锁等待的情况,影响数据库效率。所以InnoDB的可重复读没有采用行锁,而是使用了更为强大的MVCC。
可重复读数据库有四种隔离级别:读未提交/读已提交/可重复读/串行化,可重复度是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到一致的数据行。 数据行的一致性包含两部分:
InnoDB默认的隔离级别是可重复读,可以解决以上两种情况的数据行一致性问题。其中解决情况1中的数据行一致性问题就是通过MVCC多版本并发控制实现的。
MVCC的作用MVCC可以确保同一个事务,在事务起始到结束读到的某一个数据是一致的,并且多个事务之间互不阻塞。我们以一张用户表为例,说明MVCC版本控制的作用。 首先我们需要创建用户表,并向其中插入一条用户数据,SQL语句如下:
假设有A,B,C三个事务,这三个事务中在不同时刻对读取了插入用户的信息,并对用户信息进行了修改,时间线如下:
MVCC的作用可以在T5时刻体现出来,此时事务A已经提交,并且修改
MVCC原理MVCC的目的就是多版本并发控制,在InnoDB中引入MVCC就是为了解决读写冲突,MVCC主要包含三部分内容:数据库中的3个隐藏字段、UndoLog日志 、ReadView读视图,这三部分在MVCC中的作用分别如下所示:
隐藏字段隐藏字段意味着我们通过SQL语句查找不到这些字段,但是这些字段在数据库中实际存在并占用了存储空间。为了实现MVCC版本控制,InnoDB为每一行数据添加了以下3个隐藏字段:
我们使用以下SQL创建用户表,并向表中插入一条数据,新表会默认包含三个隐藏字段,表结构如下表所示。
UndoLog日志我在另外一篇文章中介绍过UndoLog日志,从名字也可以看出来,UndoLog日志主要用于回滚事务。但是InnoDB中的MVCC的快照读也使用了UndoLog。UndoLog可以分为两大类:
下文中我们以上文中的用户表以及数据为例,解释Update UndoLog的工作流程,如下为起始时
ReadView读视图ReadView就是事务进行快照读操作的时候生产的读视图,在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大) 所以我们知道ReadView主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个ReadView读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的UndoLog里面的某个版本的数据。 ReadView遵循一个可见性算法,主要是将要被修改的数据的最新记录中的DB_TRX_ID(即当前事务ID)取出来,与系统当前其他活跃事务的ID去对比(由ReadView维护),如果DB_TRX_ID跟ReadView的属性做了某些比较,不符合可见性,那就通过DB_ROLL_PTR回滚指针去取出UndoLog中的DB_TRX_ID再比较,即遍历链表的DB_TRX_ID(从链首到链尾,即从最近的一次修改查起),直到找到满足特定条件的DB_TRX_ID, 那么这个DB_TRX_ID所在的旧记录就是当前事务能看见的最新老版本。 ReadView判断可见性的原理如下,在InnoDB中,创建一个新事务之后,当新事务读取数据时,数据库为该事务生成一个ReadView读视图,InnoDB会将当前系统中的活跃事务列表创建一个副本保存到ReadView。当用户在这个事务中要读取某行记录的时候,InnoDB会将该行当前的版本号与该ReadView进行比较。具体的算法如下:
读已提交和可重复度读已提交和可重复度隔离级别下的InnoDB快照读有什么不同?答案是:ReadView生成时机的不同,从而造成读已提交和可重复度级别下快照读的结果的不同:
MVCC与幻读幻读是指,同一个事务里面连续执行两次同样的SQL语句,可能导致不同结果的问题,第二次SQL语句可能会返回之前不存在的行。举例说明:T1时刻事务A和事务B同时开启,分别进行了快照读,然后事务A向数据库中插入一条新的记录,如果事务B可以读到这条记录,就出现了"幻读",因为B第一次快照读没有读到这条数据。 MVCC是否可以解决幻读问题呢?答案是有的情况下可以解决,有的情况下不可以解决。如果事务B中的读是快照读,那么MVCC版本控制可以解决幻读问题;如果事务B中使用的是当前读,那么MVCC无法解决幻读问题。
我是御狐神,欢迎大家关注我的微信公众号:wzm2zsd 参考文档MySQL之MVCC与幻读
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 12:22:41- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |