【MySQL】MVVC机制

mysql,mvvc,机制 · 浏览次数 : 277

小编点评

**MySQL隔离级别读未提交** **隔离级别**是SQL执行过程中的安全级别,它控制了哪些事务可以被其他事务看到。 * **读提交隔离级别**: * 当事务提交之后才可被其他事务看到。 * 这确保了数据的完整性,因为其他事务只能看到已提交的事务版本。 * **可重复读隔离级别**: * 当事务开始之前已提交时才可被其他事务看到。 * 这确保了数据的一致性,因为其他事务只能看到已提交的事务版本。 **可重复读和读提交** | **隔离级别** | **读提交** | **可重复读** | |---|---|---| |读提交 | 提交后才可被读取 | 提交之前才可被读取 | | 可重复读 | 提交之前才可被读取 | 提交后才可被读取 | **隔离级别的影响** * **脏读**:当两个事务修改相同的记录时,脏读会出现,其中一个事务的读取结果与另一个事务的写入结果不同。 * **不可重复读**:当一个事务在提交之前对表中的记录进行修改,并该记录被其他事务读取时,不可重复读会出现,因为该事务可能读取到已经修改过的记录。 * **幻读**:当一个事务在提交之前对表中的记录进行修改,并该记录在提交后被其他事务读取时,幻读会出现,因为该事务读取的是未被提交的记录。 **结论** MySQL的隔离级别对读操作的影响取决于隔离级别设置。**读提交隔离级别**仅允许提交事务可被其他事务看到,而**可重复读隔离级别**则允许提交事务可被其他事务看到。

正文

MySQL隔离级别

读未提交(Read Uncommitted):某个事务读到了其他还未提交的事务对数据所作的修改,也就是某个事务只要修改了数据,其他事务就可以看到所作的修改。

这种隔离级别下会发生脏读、不可重复读、幻读。

读提交(Read Committed):某个事务提交之后,才可以被其他事务看到。

这种隔离级别下会发生不可重复读、幻读。

可重复读(Repeatable Read):一个事务在执行过程中看到的数据,总是跟这个事务在启动的时候看到的数据是一致的。

MySQL的默认隔离级别,这种隔离级别下会发生幻读。

不可重复读侧重于数据的修改,幻读侧重于数据的新增。假设事务A开始之前某个字段的值是A,事务B将它的值修改为了B,此时事务A再次查询得到的结果是B,与事务A开始时查到的值A不一致,就是不可重复读。假设事务A开始之前查询某个表只有一条记录,事务B往表中又插入了一条记录,此时事务A再次查询莫名多出一条记录,就是幻读。

串行化(Serializable):对于同一条记录,读会加读锁,写会加写锁,读和读之间不会冲突,但是读和写之间会冲突,假如读写冲突,后访问的事务需要等待前一个事务执行完毕才可以继续执行。

因为不允许事务并发执行,只能串行执行,因此不会有脏读、不可重复读、幻读问题,但是由于串行执行,性能比较差。

Read View一致性视图

InnoDB中,每个事务在开始的时候都会申请一个事物id,这样每个事务会有一个唯一的事务id,每行数据也会有多个版本,每次事务更新的时候,会生成对应的事务版本,将事物id设置到这个事务版本的trx_id中,旧的事务版本也会保留:

注意:图中的版本链不是物理上真实存在的,实际上是根据undo log版本链计算出来的。

undo log版本链

由于对数据的修改会生成undo log回滚日志,每个事务又会生成对应的事务版本,那么多个事务修改的时候就会形成一个undo log 版本链,每条数据包含两个隐藏字段,trx_id和roll_pointer:

trx_id:最近一次更新这条数据的事务id

roll_pointer:指向当前事务之前生成的那个undo log

所以多个事务串行执行的时候,每个事务都会生成一条undo log,通过roll_pointer将undo log串起来,形成undo log版本链,当没有事务需要用到这些undo log时,undo log才会被删除,假如有长事务,由于随时可能访问数据库的任何数据,在这个事务提交之前,它可能用到的undo log都将会保留,就会导致大量的占用存储空间,因此需要尽量避免长事务。

一致性视图

事务在启动的时候,InnoDb会为每一个事务创建一个数组,保存这个事务启动时,当前所有正在活跃(事务已启动但是还没提交)的事务ID,数组中事务ID最小值为低水位,已经生成过的事务的最大值的ID加1记作高水位,视图数组和高水位组成了当前事务的一致性视图,基于事务的trx_id和一致性视图可以实现读提交和不可重复读这两个隔离级别:

注:图片来自于极客时间 --- 林晓斌(丁奇):MySQL实战

对于当前事务来说,一个事务的id可能有以下三种情况:

1.在视图数组中已提交的事务中,表示这个版本是已提交的事务,那么它是可以被当前事务读到的;

2.在未开始事务中,表示这个版本的数据是由将来启动的事务生成的,对当前事务来说必然是不可见的;

3.在未提交的事务集合中,有两种情况:

(1)如果trx_id在当前事务的活跃数组中,表示这个版本是由未提交的事务生成的,对当前事务来说不可见;

(2)如果trx_id不在当前事务的活跃数组中,表示这个版本的事务已提交,对当前事务来说可见;

基于ReadView实现读提交

假设系统当前存在两个活跃的事务B和事务C:

(1)事务B第一次查询id值时会顺着undo log版本链寻找,首先会读取undo log版本链最新的值,undo log版本链中当前值为30,对应的trx_id 为30,trx_id比事务B中max_trx_id小,说明事务B在生成read view之前就存在这个活跃的事务,由于trx_id为30的事务在事务B的活跃列表中
在读提交隔离级别下,是不能读取到30这个值的,继续顺着版本链往前找,下一个是trx_id为10更新的值,trx_id =10 比事务B中的min_trx_id小,说明事务B生成read view之前,trx_id为10的事务就已经提交,所以可以读取trx_id=10的事务更新的值,事务B第一次查询得到ID的值为10;

(2)事务B在第二次查询时,会重新生成read view,此时由于事务C已提交,trx_id为30的事务不在事务B的活跃事务列表中,此时事务B是可以读取到30的,所以事务B第二次读取到ID的值为30;

实现读提交比较重要的一点就是每次在查询时都会重新生成read view。

基于ReadView实现可重复读

假设系统当前存在两个活跃的事务B和事务C:

(1)与读提交中的第一次查询一致,得到的值为10;

(2)事务B在第二次查询时,会继续使用第一次查询生成的一致性视图,此时虽然事务C已提交,但是由于没有重新生成一致性视图,trx_id为30的事务依旧在事务B的活跃事务列表中,此时事务B是不可以读取到30的,所以事务B第二次读取到ID的值为10;

实现不可重复读比较重要的一点就是整个事务都会使用一个一致性视图,不是每次查询都重新生成一致性视图。

总结:

在读提交隔离级别下,每个语句执行前都会重新算出一个一致性视图。

在可重复读隔离级别下,只在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图。

当前读

当前读指的是读取undo log版本链中最新的记录

select xx from xx lock in share;
select xx from xx for update;

lock in share mode会加读锁,for update会加写锁,这两种语句都会进行当前读。

快照读

指的是按照生成的一致性视图读取数据。

需要注意的时,如果是更新操作都是当前读。

创建持续整个事务的一个一致性快照:

start transaction with consistent snapshot; 

在读提交隔离级别下,没有意义,等效于普通的start transaction。

参考:

极客时间 --- 林晓斌(丁奇):MySQL实战

救火队队长:从零开始带你成为MySQL实战优化高手

与【MySQL】MVVC机制相似的内容:

【MySQL】MVVC机制

MySQL隔离级别 读未提交(Read Uncommitted):某个事务读到了其他还未提交的事务对数据所作的修改,也就是某个事务只要修改了数据,其他事务就可以看到所作的修改。 这种隔离级别下会发生脏读、不可重复读、幻读。 读提交(Read Committed):某个事务提交之后,才可以被其他事务看

数据特征采样在 MySQL 同步一致性校验中的实践

作者:vivo 互联网存储研发团队 - Shang Yongxing 本文介绍了当前DTS应用中,MySQL数据同步使用到的数据一致性校验工具,并对它的实现思路进行分享。 一、背景 在 MySQL 的使用过程中,经常会因为如集群拆分、数据传输、数据聚合等原因产生流动和数据复制。而在通常的数据复制过程

小白也能懂的Mysql数据库索引详解

一文让你彻底了解:主键索引/二级索引,聚簇索引/非聚簇索引,回表/索引覆盖,索引下推,联合索引/最左联合匹配,前缀索引,explain

mysql查看用户的过期时间

1. mysql查看用户的过期时间的方法 在MySQL中,用户的过期时间(也称为账户过期日期)是一个可选项,用于确定某个MySQL用户账户何时到期。但是,值得注意的是,并非所有的MySQL安装或版本都支持直接设置用户账户的过期时间。特别是,标准的MySQL用户表(如mysql.user)并没有一个专

【冷启动#1】实用的MySQL基础

简单安装一下MySQL Windows下(5.7.x) 本体安装 1、首先先下载安装包,名字如下: mysql-5.7.19-winx64.zip 2、配置环境变量,将解压之后的bin目录添加一下 3、在解压目录下创建my.ini文件,内容如下: [ client ] port=3306 defau

小白也能懂的Mysql数据库索引详解

核心概念 主键索引/二级索引 聚簇索引/非聚簇索引 回表/索引覆盖 索引下推 联合索引/最左联合匹配 前缀索引 explain 一、[索引定义] 1.索引定义 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法

解读MySQL 8.0数据字典的初始化与启动

本文分享自华为云社区《MySQL全文索引源码剖析之Insert语句执行过程》,作者:GaussDB 数据库。 本文主要介绍MySQL 8.0数据字典的基本概念和数据字典的初始化与启动加载的主要流程。 MySQL 8.0数据字典简介 数据字典(Data Dictionary, DD)用来存储数据库内部

MySQL入门到实战详细教程

MySQL介绍 MySQL是一个开源的关系型数据库管理系统(RDBMS),由瑞典 MySQL AB 公司开发,属于 Oracle 旗下产品,它广泛应用于各种Web应用程序和网站,MySQL使用结构化查询语言(SQL)进行数据的管理和操作。 MySQL主要特点 开源免费:MySQL是一个开源项目,可以

《软件性能测试分析与调优实践之路》第二版-手稿节选-Mysql数据库性能定位与分析

在做MySQL数据的性能定位前,需要先知道MySQL查询时数据库内部的执行过程。只有弄清SQL的执行过程,才能对执行过程中的每一步的性能做定位分析。如图6-2-1所示。 图6-2-1 从图中可以看到,当查询出数据以后,会将数据先返回给执行器,此时执行器先将结果写到查询缓存里面,这样在下次查询相同的数

MySQL 存储函数及调用

本文主要介绍了MySQL存储函数及调用的方法,介绍了存储函数的示例,如何在MySQL中创建存储函数,以及介绍了MySQL中如何创建触发器,简简单单,一目了然。