MySQL -- MVCC

前言

最近在学MySQL,决定记录一下,能写多少写多少,不定时更新,加油。

正文

分几个部分来吧,大致如下:

  • 字符集与比较规则

  • 行格式与数据页

  • InnoDB索引

  • 访问方法与连接

  • explain 与 子查询优化

  • redoundo 日志

  • MVCC 与 锁

本文为第四部分 MVCC 原理解析


主要就是想先写这个, 其他的后面有空再补~

由于我们跳过一些东西, 下面说MVCC的原理可能会各种懵


所以, 我们先简单过几个点吧.

一、温故知新 -- 两个隐藏列的含义

行格式的时候说过,InnoDB会为每行加上两个隐藏列(row_id并不是必加的)trx_idroll_pointer 这俩哥们简直生猛的一塌糊涂.

小声明:
事务T1的编号是100
事务T2的编号是200

  • trx_id 这个明显是事务ID的意思, 就是记录一下最近操作此条记录的事务ID. 比如事务T1中插入了一条记录X,那X的trx_id就是100,如果在T1中继续操作这条记录是不会修改X的trx_id的.如果事务T2修改了这X记录,那么其trx_id就变成200.
  • roll_pointer字面意思就是回滚指针, 指针存放的是一个地址, 指向了某个值. 它指向的是一条undo日志记录.

这里简单提一下undo日志,后面会专门写一篇详细讲的[有生之年系列]。

一条undo日志就是一条记录, 存放在页中,叫undo日志页.大致分为两种,插入类型(insert)和修改类型(updatedelete),这里只需要知道他们有一个很大区别:插入类型的undo日志是没有指向下一条undo日志的属性的,也就是说他们组成了一个undo日志链表,又称版本链

undo日志链表(版本链)
  • 第一条是真实记录,0是记录类型,H是记录头,300是trx_id R是roll_pointer, 1、3.. 是记录的真实数据
  • 可以看到每条undo日志都有一个事务ID(图中我画在最后面,实际并不是存在最后),这个属性其实是叫old trx_id, 表示当前undo日志对应的事务ID,也称此版本的创建事务ID
  • 插入类型undo日志没有old roll_pointer指向上一条roll_pointer,因为它本来就是版本链的第一条
  • 这条undo链表可以看出,此记录由事务ID为100的事务插入,在事务ID为200的事务中修改了两次,而事务ID为300的事务正在修改此记录。
  • 记住这个顺序,后面有用。

二、老生常谈 -- 隔离级别

说这个隔离级别之前,我们先想想为什么要有这个东东?

其实每个新技术或新名词的出现, 都可以问这几个问题
1.这个东东解决了什么问题吗?
2.现有的技术解决不了吗?
3.如果能, 它比当前的解决方案强在哪些方面呢?
4.不足或改进之处.

  • 以上纯属扯淡

随着互联网的发展,并发已经是一道绕不开的坎。各种问题都不断冒出来,那并发事务访问数据库会发生什么样的问题呢?

一个一个来看下。

  • 脏写(Dirty Write
    T1事务开启
    T1修改:X=5
    T2事务开始
    T2修改:X=6
    T2事务提交
    T1事务提交

结果:X=5

这个时候T2的事务所做修改就丢失了.

一个事务修改了另一个未提交事务修改过的数据,此为脏写。

  • 脏读(Dirty Read
    数据状态:X=5
    T1事务开启
    T2事务开始
    T2修改:X=6
    T1读取:X=6
    T2事务回滚
    T1事务提交

T1读到的X=6,库中X=5

一个事务读取了另一个未提交事务修改过的数据,此为脏读。

  • 不可重复读(Non-Repeatable Read
    事务T1开启
    事务T2开启
    T1读取:X=5
    T2修改:X=6
    事务T2提交
    T1读取:X=6
    。。。

T1两次读取到的同一条记录的值不一样。

每次事务提交后,当前事务都能读取到记录的最新值,此为不可重复读。

  • 幻读(Phantom
    库中数据: X=6
    事务T1开启
    事务T2开启
    T1读取:X>5 (得到一条X=6)
    T2新增:X=7
    T1读取:X>5 (得到两条X=6和X=7)
    。。。

T1第二次读取的记录数量比第一次读取到的记录数量多。

如果事务T1根据条件N查询数据,事务T2添加了满足条件N的记录并提交了,T1再次根据N查询数据能查询T2新增的记录,此为幻读。

注意几个点:

  • 不可重复读是针对单条记录的改动(包括删除与修改)
  • 幻读是针对查询条件的范围内记录的新增
  • 幻读只是针对新增,如果有范围内记录的删除或修改,都属于不可重复读

为了解决这些问题,有一帮人提出了一个SQL标准,给出了四种隔离级别,用以解决上诉问题:

  • READ UNCOMMITTED
  • READ COMMITTED
  • READ REPEATABLE
  • SERIALABLE

SQL标准中规定,

  • READ UNCOMMITTED 解决脏写
  • READ COMMITTED 解决脏读
  • READ REPEATABLE 解决脏读与不可重复读
  • SERIALABLE 解决幻读

数据库对脏写的问题是零容忍,哪怕最低的隔离级别都不允许出现

然而MySQL里的大佬还是牛逼,他们在READ REPEATABLE 级别就已经解决了幻读问题。

实现一般有两种方式,第一是加锁,第二是MVCC

实际上,二者都有用到.


三、千呼万唤 -- MVCC的原理

ReadView登场

先看下其大致结构

ReadView结构
  • m_ids 存放当前系统中活跃的事务集合
  • min_trx_idm_ids中最小的事务ID
  • max_trx_id 分配给下一个开启事务的事务ID
  • creator_trx_id 创建此ReadView的事务ID

事务ID注意两点:

  • 只有在对表中的记录做改动时(执行INSERTDELETEUPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。
  • 按分配顺序递增

怎么突然蹦出来一个ReadView? 先看看怎么用.

如果你不是一条鱼的话,应该还记得前面说过,每条记录都有一个版本链吧,当一个事务要访问某条记录时,对着这个ReadView的操作是这样的:

  • 判断trx_idcreator_trx_id是否相等,是则意味着此版本正在被当前事务操作,可以访问
  • 判断trx_id是否小于min_trx_id,表示此版本的生成事务已经提交,可以访问
  • 判断trx_id是否大于等于max_trx_id,表示此版本的生成事务已经提交,可以访问
  • 判断trx_id是否在m_ids中,若不在,则意味着此版本的创建事务已经提交,可以访问;若在,则表明此版本在创建ReadView时还在活动,不能访问。

若无法访问则顺着版本链找下一个版本,如果到最后一个版本(也就是Insert的undo日志)仍无法访问,那么此记录对当前事务不可见。

现在知道这玩意有多牛逼了吧~

那跟隔离级别有啥关系呢?

READ COMMITTEDREAD REPEATABLE 的最大区别就是生成ReadView的时机不一样

  • READ REPEATABLE 事务开启时生成
  • READ COMMITTED 每次查询前生成

想想ReadView与其生成时机如何能解决脏读/幻读问题~


喊我来加班,到公司都写完一篇MVCC了,还没见到人~~~~[允悲]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • 什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点。 原子性:要不全部成功,要不全部撤销 隔...
    jiangmo阅读 1,082评论 0 3
  • MVCC(Mutil-Version Concurrency Control),就是多版本并发控制。MVCC 是一...
    yes的练级攻略阅读 1,661评论 2 2
  • MVCC: 1什么是MVCC? MVCC是一种多版本并发控制机制。 2 MVCC的作用? 锁的开销毕竟很大...
    机智的老刘明同志阅读 987评论 0 3
  • 1.Mysql特点 可靠、事务、开源。 2.MySQL架构 接入层,连接通信、权限验证、连接池、线程管理 服务层,...
    不是明天阅读 4,449评论 1 0
  • MVCC(Multi Version Concurrency Control的简称),代表多版本并发控制。与MVC...
    浆水面韭菜花阅读 58,424评论 21 87