本文给大家详细的类介绍下MVCC的内容,MVCC对大家的工作和面试都是非常重要的内容。

一、前置内容

1.ACID

  在看MVCC之前我们先补充些基础内容,首先来看下事务的ACID。

2.MySQL的核心日志

  在MySQL数据库中有三个非常重要的日志binlog,undolog,redolog.
  举例演示为:

3.隔离级别

  MySQL的事务隔离级别有四个,分别为:

  事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采取必要的隔离机制,就可能发生以下问题:

问题 描述
脏读 一个事务读到另一个事务未提交的更新数据,所谓脏读,就是指事务A读到了事务B还没有提交的数据,比如银行取钱,事务A开启事务,此时切换到事务B,事务B开启事务–>取走100元,此时切换回事务A,事务A读取的肯定是数据库里面的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读
幻读 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。
不可重复读 在一个事务里面的操作中发现了未被操作的数据 比方说在同一个事务中先后执行两条一模一样的select语句,期间在此次事务中没有执行过任何DDL语句,但先后得到的结果不一致,这就是不可重复读
隔离级别 描述
READ_UNCOMITTED 读未提交(脏读)最低的隔离级别,一切皆有可能。
READ_COMMITED 读已提交,ORACLE默认隔离级别,有幻读以及不可重复读风险。
REPEATABLE_READ 可重复读,解决不可重复读的隔离级别,但还是有幻读风险。
SERLALIZABLE 串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了

数据库的并发场景:

  • 读读:不会存在任何问题,也不需要并发控制
  • 读写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读,需要MVCC控制
  • 写写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失

二、MVCC

1.什么是MVCC

  MVCC(Multi-Version Concurrency Control):多版本并发控制,是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
  MVCC 在 MySQL InnoDB 中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

2.什么是当前读和快照读

  在学习 MVCC 多版本并发控制之前,我们必须先了解一下,什么是 MySQL InnoDB 下的当前读和快照读。

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

  其实MVCC 就是为了实现读-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现.

3.三者关系

  当前读,快照度和MVCC的关系是如何的呢?

  1. MVCC 多版本并发控制是(维持一个数据的多个版本,使得读写操作没有冲突) 的概念,只是一个抽象概念,并非实现
  2. 因为 MVCC 只是一个抽象概念,要实现这么一个概念,MySQL 就需要提供具体的功能去实现它,(快照读就是 MySQL 实现 MVCC 理想模型的其中一个非阻塞读功能)。而相对而言,当前读就是悲观锁的具体功能实现
  3. 要说的再细致一些,快照读本身也是一个抽象概念,再深入研究。MVCC 模型在 MySQL 中的具体实现则是由 3 个隐式字段,undo 日志 ,Read View 等去完成的,具体可以看下面的 MVCC 实现原理

4.MVCC的好处

  首先我们要清楚数据库中的并发场景有三种,分别是:

  然后来看MVCC的好处:
  多版本并发控制(MVCC)是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 所以 MVCC 可以为数据库解决以下问题:

  1. 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
  2. 同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

5.MVCC工作原理

  MVCC 的目的就是多版本并发控制,在数据库中的实现,就是为了解决读写冲突,它的实现原理主要是依赖记录中的 3个隐式字段,undo日志 ,Read View 来实现的。

5.1 三个隐藏字段

  DB_ROW_ID 是数据库默认为该行记录生成的唯一隐式主键,DB_TRX_ID 是当前操作该记录的事务 ID ,而 DB_ROLL_PTR 是一个回滚指针,用于配合 undo日志,指向上一个旧版本
举例如:


  从上面,我们就可以看出,不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,既链表,undo log 的链首就是最新的旧记录,链尾就是最早的旧记录.
undolog:回滚日志,保存了事务发生之前的数据的一个版本,作用:

  1. 可以用于回滚
  2. 同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。
  3. 事务开始之前,将当前事务版本生成 undo log,undo log 也会产生 redo log 来保证 undo log 的可靠性。
  4. 当事务提交之后,undo log 并不能立马被删除,而是放入待清理的链表。
  5. 由 purge 线程判断是否有其它事务在使用 undo 段中表的上一个事务之前的版本信息,从而决定是否可以清理 undo log 的日志空间。

5.2 ReadView

  什么是 Read View,说白了 Read View 就是事务进行快照读操作的时候生产的读视图 (Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的 ID (当每个事务开启时,都会被分配一个 ID , 这个 ID 是递增的,所以最新的事务,ID 值越大)

  所以我们知道 Read View 主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个 Read View 读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。

  Read View遵循一个可见性算法,主要是将要被修改的数据的最新记录中的 DB_TRX_ID(即当前事务 ID )取出来,与系统当前其他活跃事务的 ID 去对比(由 Read View 维护),如果 DB_TRX_ID 跟 Read View 的属性做了某些比较,不符合可见性,那就通过 DB_ROLL_PTR 回滚指针去取出 Undo Log 中的 DB_TRX_ID 再比较,即遍历链表的 DB_TRX_ID(从链首到链尾,即从最近的一次修改查起),直到找到满足特定条件的 DB_TRX_ID , 那么这个 DB_TRX_ID 所在的旧记录就是当前事务能看见的最新老版本.


举例说明:

分析:

第二种情况:

分析:

最后完成的绘图:

总结:能否看到事务修改的数据,取决于可见性算法,可见性算法比较的时候又取决于ReadView中的结果值!因为在不同隔离级别的时候,生成ReadView的时机是不同的RC:每次执行时快照读都会重新生成新的ReadViewRR:只有当第一次事务进行快照读的时候才会生成ReadView,之后的快照读操作都会复用当前的ReadView 。

好了本文就介绍到这里,希望对有有所帮助哦

MySQL数据库的核心MVCC详解相关推荐

  1. 数据库服务器配置参数修改,MySQL数据库服务器端核心参数详解和推荐配置2

    l  innodb_commit_concurrency 含义:同一时刻,允许多少个线程同时提交InnoDB事务,默认值为0,范围0-1000. 0      - 允许任意数量的事务在同一时间点提交: ...

  2. 第一章笔记MySQL数据库的安装目录详解

    MySQL数据库的安装目录详解 bin目录:用于存放一些可以执行的文件,如mysql.exe;,mysqld.exe;mysqlshow.exe等. data目录:用于存放一些日志文件以及数据库. i ...

  3. MySQL数据库update语句使用详解

    MySQL数据库update语句使用详解 本篇文章我们来讲讲如何对MySQL数据库进行更新操作,对数据库进行增删改查操作是我们必会的基础之一,会了这个增删改查我们可以在这基础上去编写更多的东西,废话不 ...

  4. mysql数据库字段变形_详解如何利用amoeba(变形虫)实现mysql数据库读写分离

    摘要:这篇MySQL栏目下的"详解如何利用amoeba(变形虫)实现mysql数据库读写分离",介绍的技术点是"MySQL数据库.数据库读写分离.amoeba.MySQL ...

  5. mysql数据库的函数_详解数据库_MySQL: mysql函数

    一.内置函数 1.数学函数 rand() round(num) ceil(num) floor(num) 随机 四舍五入 向上取整 向下取整 2.字符串函数 length() 字节长度 char_le ...

  6. MySQL数据库 my.cnf文件详解

    文章目录 MySQL5.7的配置文件详解 MySQL5.7的配置文件详解 cat /etc/my.cnf #客户端设置,即客户端默认的连接参数 [client] #默认连接端口 port = 3306 ...

  7. MySQL数据库基础:数据类型详解-文本字符串类型

    前言 正好趁着这次一起学习复习一下MySQL数据库的基本知识.也是一直在用这个数据库,有些基础的知识点长久不用就会遗忘,就比如数据类型溢出的问题,很多时候建表的时候随便给定个类似,结果导入数据的时候报 ...

  8. python操作mysql数据库的常用方法使用详解

    python操作mysql数据库 1.环境准备: Linux 安装mysql: apt-get install mysql-server 安装python-mysql模块:apt-get instal ...

  9. MySQL数据库表分区功能详解

    1.什么是表分区? mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看),一张表主要对应着三个文件,一个是frm存放表 ...

最新文章

  1. R语言数据包自带数据集之mtcars数据集字段解释、数据导入实战
  2. Python 机器学习库 Top 10,你值得拥有!
  3. mysql的如何输入dateadd_mysql中date_add()函数的使用?
  4. python简笔画绘制 数据驱动绘图恐龙_使用python turtle绘制简笔画大白-Go语言中文社区...
  5. 腾讯云前端性能优化大赛火热招募中!
  6. GO tcp server demo
  7. 数学建模 匈牙利算法求解整数规划基本原理与编程实现
  8. LeetCode-150-Evaluate Reverse Polish Notation
  9. glob,正则表达式元字符,扩展正则表达式总结
  10. 各种小巧的Hello World
  11. springcloud注册中心Eureka英 [juəˈri:kə]的基本搭建
  12. Linux下网站搭建(2)---Mysql安装和基本操作
  13. delphi7 增加管理员权限_EHR系统的权限设计
  14. MT2503处理器性能介绍,MT2503/MT2503A/MT2503D芯片资料下载
  15. 2020电赛F题–简易无接触温度测量与身份识别装置
  16. nacos 安装包下载 linux+windows
  17. sublime text3 字体样式_Sublime Text3 Github最受欢迎主题字体推荐!
  18. SIPM模拟器 MIPS汇编语言实现读取文件
  19. c语言字符串的小程序,微信小程序字符串转换为数字如何实现
  20. zbb20181006 maven配置阿里云中央仓库

热门文章

  1. java根据前序和中序建树_(Java实现)二叉树---根据前序、中序、后序数组还原二叉树...
  2. JavaScript DOM 删除子节点的;两种操作
  3. C++小游戏之停电救援
  4. 微分法MATLAB语言程序,matlab微积分运算命令与例题pdf
  5. 网上如何赚钱?教你利用知识变现来赚钱!
  6. JavaScript随手笔记---保留小数位
  7. 北航计算机组成实验project4,北航fpga实验的报告.docx
  8. 模板配置--后台管理系统
  9. Unirech-阿里云国际版云服务器ecs实例使用中的常见问题汇总
  10. Leetcode:347. 前 K 个高频元素(C++)