MySQL学习记录

MySQL -- MVCC

2019-07-13  本文已影响0人  sunyelw

前言

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

正文

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

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


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

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


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

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

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

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


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

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

undo日志链表(版本链)

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

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

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

  • 以上纯属扯淡

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

一个一个来看下。

结果:X=5

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

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

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

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

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

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

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

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

注意几个点:

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

SQL标准中规定,

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

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

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

实际上,二者都有用到.


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

ReadView登场

先看下其大致结构

ReadView结构

事务ID注意两点:

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

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

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

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

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

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

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

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


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

上一篇下一篇

猜你喜欢

热点阅读