MYSQL进阶

目录

1、索引

1.1 最左前缀法则

1.1.1、未遵守最左前缀法则。

1.1.2、使用范围查询,也会使右边的索引列失效

1.1.3  索引列运算会造成索引列失效

1.1.4 字符串不加引号,索引也会失效

1.1.5 模糊查询索引部分失效

1.1.6 or连接有可能造成索引失效

1.1.7 数据分布影响索引是否失效

1.2 SQL 提示

1.3 覆盖索引

1.4 前缀索引

1.5 单列索引&联合索引

1.6 索引的设计原则

2、SQL优化

2.1、insert优化  

 2.2 主键优化

 2.3 order by 优化

2.4 gruop by优化

2.5 limit 优化

2.6 count 优化

2.7 update 优化

 2.8优化总结

3、锁 

3.1 全局锁

3.2 表级锁

3.2.1、表共享读锁(读锁)

3.2.3 元数据锁(MDL)

 3.2.4、意向锁

3.3 行级锁

3.3.1 行锁的共享锁和排他锁

 3.3.2 行锁:间隙锁+邻键锁

4、InnoDB引擎 

InnoDB和MyISAM的区别是什么?

MyISAM索引的原理

4.1 逻辑存储结构

4.2 InnoDB引擎 内存结构

4.2.1 缓冲池 

 4.2.2 更改缓冲区

 4.2.3 自适应哈希索引

 4.2.4 日志缓冲区

 4.3 InnoDB磁盘结构

 4.4 后台线程

4.3 事务原理

4.3.1 Redolog

4.3.2 undolog

 4.4 MVCC

4.4.1 MVCC基本概念

4.4.2 MVCC实现原理--undolog版本链在事务中的体现 

 4.4.3 readView介绍

 MYSQL体系结构

MYSQL进阶_第1张图片

1、索引

基于B+树的索引图,包括键值、数据、指针、页/块

MYSQL进阶_第2张图片

索引分为主键索引和二级索引:

主键索引:

数据表的主键列使用的就是主键索引。

一张数据表有只能有一个主键,并且主键不能为 null,不能重复。

在 MySQL 的 InnoDB 的表中,当没有显示的指定表的主键时,InnoDB 会自动先检查表中是否有唯一索引且不允许存在 null 值的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。

二级索引:

聚集索引和二级索引的区别

二级索引又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置。

唯一索引,普通索引,前缀索引等索引属于二级索引。

  1. 唯一索引(Unique Key) :唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引。 建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性,而不是为了查询效率。
  2. 普通索引(Index) :普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和 NULL。
  3. 前缀索引(Prefix) :前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小, 因为只取前几个字符。
  4. 全文索引(Full Text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6 之前只有 MYISAM 引擎支持全文索引,5.6 之后 InnoDB 也支持了全文索引。

MYSQL进阶_第3张图片

 聚集索引和非聚集索引

聚集索引:

聚簇索引即索引结构和数据一起存放的索引,并不是一种单独的索引类型。InnoDB 中的主键索引就属于聚簇索引。

优缺点:

优点 :

  • 查询速度非常快 :聚簇索引的查询速度非常的快,因为整个 B+树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。相比于非聚簇索引, 聚簇索引少了一次读取数据的 IO 操作。
  • 对排序查找和范围查找优化 :聚簇索引对于主键的排序查找和范围查找速度非常快。

缺点 :

  • 依赖于有序的数据 :因为 B+树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或 UUID 这种又长又难比较的数据,插入或查找的速度肯定比较慢。
  • 更新代价大 : 如果对索引列的数据被修改时,那么对应的索引也将会被修改,而且聚簇索引的叶子节点还存放着数据,修改代价肯定是较大的,所以对于主键索引来说,主键一般都是不可被修改的。

非聚集索引:

非聚簇索引介绍

非聚簇索引即索引结构和数据分开存放的索引,并不是一种单独的索引类型。二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引

非聚簇索引的叶子节点并不一定存放数据的指针,因为二级索引的叶子节点就存放的是主键,根据主键再回表查数据。

非聚簇索引的优缺点

优点 :

更新代价比聚簇索引要小 。非聚簇索引的更新代价就没有聚簇索引那么大了,非聚簇索引的叶子节点是不存放数据的

缺点 :

  • 依赖于有序的数据 :跟聚簇索引一样,非聚簇索引也依赖于有序的数据
  • 可能会二次查询(回表) :这应该是非聚簇索引最大的缺点了。 当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。

1.1 最左前缀法则

如果索引了多列(联合索引),联合索引原理索引原理:联合索引(最左前缀原则)_联合索引最左原则原理_底小治的博客-CSDN博客

索引失效情况

1.1.1、未遵守最左前缀法则。

要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列,如果跳过一列,索引部分失效(后面的字段索引失效)

如下,假定建立索引profession、age、status,那么根据最左前缀法则,第一条语句是按索引方式查询的,第二个也是,第三个也是,而第四个缺少了profession索引,查询时并未按索引方式查询,第五个也不符合最左前缀法则,不按索引方式进行查询。

MYSQL进阶_第4张图片

1.1.2、使用范围查询,也会使右边的索引列失效

由图可见status、age索引失效

 而采用>=查询,可以避免索引失效的问题

1.1.3  索引列运算会造成索引列失效

对phone建立索引,如果对其列数据做运算操作

select * from tb_user where substring(phone,10,2)='15'

可得执行结果,执行了全表扫描,索引失效

1.1.4 字符串不加引号,索引也会失效

字符串类型字段使用时,不加引号,索引将失效

explain select*from tb_user where profession='软件工程'and age=31 and status=0;

explain select*from tb_user where phone=17855973545

1.1.5 模糊查询索引部分失效

如果仅仅是尾部模糊匹配,索引不会失效,如果是头部模糊匹配,索引失效

尾部模糊匹配,索引不失效

select *from tb_user where profession like '软件%'

 头部模糊匹配,索引失效

select* from tb_user where profession like '%工程';

1.1.6 or连接有可能造成索引失效

用or分隔开的条件,如果or前的条件中列有索引,而后面的列没有索引,那么涉及的索引都不会被用到

由于age没有索引,所以即便id phone有索引,索引也会失效,所以需要针对age也要建立索引

1.1.7 数据分布影响索引是否失效

如果MYSQL评估使用索引比全表更慢,则不使用索引

如果说查询出来的数据占表的大部分,走全表搜索比走索引快时,会走全表扫描,不走索引 

1.2 SQL 提示

MYSQL进阶_第5张图片

SQL提示是优化数据库的重要手段,简单来说就是在SQL语句中加入一些人为的提示来达到优化操作的目的

1.3 覆盖索引

创建一个索引,该索引包含查询中用到的所有字段,称为“覆盖索引”。

使用覆盖索引,MySQL 只需要通过索引就可以查找和返回查询所需要的数据,而不必在使用索引处理数据之后再进行回表操作。

覆盖索引可以一次性完成查询工作,有效减少IO,提高查询效率。

也就是说,查询的列和索引的列一致,可以使用覆盖索引,查询中应该尽量使用覆盖索引,减少使用 select * from

创建联合索引

ALTER TABLE `staffs` ADD INDEX idx_staffs_nameAgePos(`name`, `age`, `pos`);

 使用覆盖索引查询

EXPLAIN SELECT `name`,age,pos FROM staffs WHERE `name`='July' AND age=25 AND pos='dev';

以下这些查询也可以使用覆盖索引: 

-- 范围查询
EXPLAIN SELECT `name`,age,pos FROM staffs WHERE `name`='July' AND age>25 AND pos='dev';
-- 查询条件中使用部分字段
EXPLAIN SELECT `name`,age,pos FROM staffs WHERE `name`='July' AND age=25;
-- 查询列中使用部分字段
EXPLAIN SELECT `name` FROM staffs WHERE `name`='July' AND age=25;

1.4 前缀索引

MYSQL进阶_第6张图片

1.5 单列索引&联合索引

单列索引

MYSQL进阶_第7张图片

 单列索引与联合索引

MYSQL进阶_第8张图片

1.6 索引的设计原则

MYSQL进阶_第9张图片

2、SQL优化

2.1、insert优化  

如果要一次性插入上千、万条数据,可以采用批量插入、手动提交事务、主键顺序插入等

批量插入:

大批量插入数据:

 如果一次性需要插入大量数据,使用insert语句的插入性能低下,可以采用load指令进行插入

MYSQL进阶_第10张图片

手动提交事务

MYSQL进阶_第11张图片

 主键顺序插入

主键顺序插入性能高于乱序插入

 2.2 主键优化

主键设计原则:

1、满足业务需求的情况下,尽量降低主键的长度

2、插入数据时,尽量按顺序插入,选择使用AUTO_INCREMENT作为自增主键

3、尽量不要使用UUID做主键或其他自然主键,如身份证号(乱序插入造成页分裂,过长的主键,检索起来也耗时耗资源)

数据组织方式:在InnoDB存储引擎中,表数据是根据主键顺序组织存放的,这种存储方式称为索引组织表

MYSQL进阶_第12张图片

 MYSQL进阶_第13张图片

 主键顺序插入时,数据按顺序存满各页,如下图1page存满8个行数据,满了之后第二页开始存储第九个行数据,第二页写满了之后写第三页。

MYSQL进阶_第14张图片

主键乱序插入时 ,会产生页分裂

要插入键值为50的行数据时,因为B+树存储叶子节点是按顺序存储的,需要放入1page,1page还有部分空间,但是存储空间小于键值为50的行数据,无法插入1page

MYSQL进阶_第15张图片

 此时会开辟一个新数据页,将1page中一半page转入到新page页,重新设置指针,从而产生页分裂。

MYSQL进阶_第16张图片

 当删除记录时,可能会产生页合并,产生页合并的阈值可以由自己设置 MERGE_THRESHOLD

删除13、14、15、16时,会产生合并

MYSQL进阶_第17张图片

 

 2.3 order by 优化

优化方法:

1、根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则

2、尽量使用覆盖索引,一个索引包含了所有需要查询的字段值,那么就称为覆盖索引

3、多字段排序,如一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)

4、如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size

数据库排序主要用以下两种方式

 using index 性能更好,using filesort差一些,尽量使用using index进行排序

select id,age,phone from tb_user order by age

可以用explain 查询该语句具体信息

 可知该语句采用的是using filesort,性能较差

将age,phone设置为索引,再进行排序

create index_idx _user_age_phone on tb_user(age,phone)

再进行排序,可用explain查看该语句信息,可知语句采用的是using index

 对phone,age进行排序,并用explain查看该语句信息,可以看到此语句用了两种排序方式

因为建立索引时先对age建立,再对phone建立索引,而排序时两者顺序颠倒,违反最左前缀原则

什么是最左前缀原则:什么是最左前缀原则?什么是最左匹配原则?_社会搬运工的博客-CSDN博客

所以使用了 using filesort

对于升序,降序排序也可以做优化,只要建立对应的索引即可

MYSQL进阶_第18张图片

2.4 gruop by优化

通过创建索引提高gruop by语句的性能

在分组操作时,可以通过索引来提高效率

分组操作时,索引的使用也是满足最左前缀法则的,如不满足,则会采用临时表,降低效率

MYSQL进阶_第19张图片

 各类索引失效的情况以及解决方法:

首先建立索引

create index idx_user_pro_age_sta on tb_user(profession,age,status)

分析下列语句

explain select profession,count(*) from tb_user group by profession;

可得性能分析为,可见用到了索引

 再分析以下语句

explain select age,count(*) from tb_user group by age

见性能分析,用到了临时表,不满足最左前缀原则,age是乱序的

 再分析以下语句

explain select profession,age,count(*) from tb_user group by profession,age

见性能分析,符合最左前缀原则

 再分析以下语句

explain select age,count(*) from tb_user where profession ='软件工程' group by age

见性能分析,符合最左前缀原则

2.5 limit 优化

优化思路:一般分页查询时,通过创建覆盖索引能够比较好的提高性能,可以通过覆盖索引+子查询的形式进行优化

设置id为主键索引,,根据排序进行分页查询,建立sql语句

select * from tb_sku s,(select id from tb_sku order by id limit 9000000,10) a where s.id=a.id 

2.6 count 优化

InnoDB引擎执行count时,需要将数据一行一行从引擎内读出来,然后累积计数

优化思路:自己计数

MYSQL进阶_第20张图片

 count(*)性能最优,尽量使用count(*)

2.7 update 优化

在字段值没有建立索引的情况下,用where或其他的方式去绑定字段值更新,会触发表锁,让此表在此期间无法进行修改。如语句

update course set name='123' where name='PHp';

触发表锁,在commit之前,无法对此表进行修改

优化方式:对要进行where或其他方式绑定的字段建立索引,如上语句,即对name建立索引

create index_idx_course_name on course(name)

如此便不会加表锁,避免了行锁升级为表锁

优化:

MYSQL进阶_第21张图片

 2.8优化总结

MYSQL进阶_第22张图片

3、锁 

MYSQL中的锁,按照锁的颗粒度可分为三类

1、全局锁:锁定数据库中的所有表

2、表级锁:每次操作锁死一张表

3、行级锁:每次操作锁住对应的行数据

3.1 全局锁

全局锁应用场景:做全库的逻辑备份,对所有表进行锁定,从而获取一致性视图,保证数据的完整性。

加锁后整个数据库实例就处于只读状态,后续的DML、DDL等语句,已经更新操作的事务提交语句都将被阻塞。

MYSQL进阶_第23张图片

3.2 表级锁

表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用于MyISAM,InnoDB,BDB等存储引擎中

对于表锁,分为两类

3.2.1、表共享读锁(读锁)

读锁阻塞更新/写操作,当其他用户想对加了读锁的表施加写操作,需要等释放读锁后才能操作

 读操作并不会阻塞

3.2.2、表独占写锁(写锁)

写锁阻塞其他用户的读写操作,当前对其上锁的操作用户可对其进行读写操作

总结:

读锁不会阻塞其他客户端的读,但是会阻塞写。写锁会阻塞其他客户端的读,也会阻塞其他客户端的写

语法:

1、加锁:lock tables 表名... read/write

2、释放锁:unlock tables /客户断开连接

3.2.3 元数据锁(MDL)

MDL加锁过程是系统自动控制,无需显示使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据一致性,在表上有活动事务时,不可对元数据进行写入操作

在MYSQL5.5 中引入MDL,当对某一张表进行增删改查时,加入了MDL读锁(共享),当对表结构进行变更操作时,加入MDL写锁(排他)

MYSQL进阶_第24张图片

 3.2.4、意向锁

为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中加入意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少锁的检查。

举个例子,线程A对第三行数据进行更新操作,从而对id为3的行数据上了行锁,同时,也给整个表上了意向锁。当线程B前来操作这个表时,先会判断该意向锁与线程要上的锁是否兼容;

如果不兼容,只能等待线程A将锁释放。 

MYSQL进阶_第25张图片

 意向锁与其他锁的兼容性

意向锁:

1、意向共享锁(IS):与表锁共享锁(read)兼容,与表锁排他锁(write)互斥

2、意向排他锁(IX):与表锁共享锁(read)及排他锁(write)都互斥。意向锁之间不会互斥

3.3 行级锁

行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。

InnoDB的数据是基于索引组织的,行锁是通过对索引的索引项加锁实现的。

对于行级锁,主要分为以下三类

1、行锁,锁定单个行记录的锁,防止其他事务对此进行update和delete。在RC、RR隔离级别下都支持。

2、间隙锁(next-key):锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。

 3、临键锁(next-key lock):行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙GAP。在RR隔离级别下支持

其中 隔离性 分为了四种:

READ UNCOMMITTED:可以读取未提交的数据,未提交的数据称为脏数据,所以又称脏读。此时:幻读,不可重复读和脏读均允许;
READ COMMITTED:只能读取已经提交的数据;此时:允许幻读和不可重复读,但不允许脏读,所以RC隔离级别要求解决脏读;
REPEATABLE READ:同一个事务中多次执行同一个select,读取到的数据没有发生改变;此时:允许幻读,但不允许不可重复读和脏读,所以RR隔离级别要求解决不可重复读;
SERIALIZABLE: 幻读,不可重复读和脏读都不允许,所以serializable要求解决幻读;

行锁使用的注意事项:

InnoDB 的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。当我们执行 UPDATEDELETE 语句时,如果 WHERE条件中字段没有命中唯一索引或者索引失效的话,就会导致扫描全表对表中的所有行记录进行加锁。这个在我们日常工作开发中经常会遇到,一定要多多注意!!!

不过,很多时候即使用了索引也有可能会走全表扫描,这是因为 MySQL 优化器的原因。

3.3.1 行锁的共享锁和排他锁

1、共享锁:允许一个事务去读一行,组织其他事务获得相同数据集的排他锁

2、排他锁:允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁

MYSQL进阶_第26张图片

MYSQL进阶_第27张图片

 3.3.2 行锁:间隙锁+邻键锁

MYSQL进阶_第28张图片

索引上的范围查询(唯一索引) 会在该范围内,全部添加临键锁

MYSQL进阶_第29张图片

 对id为5的行数据执行更新操作,会在id=3和id=7之间加间隙锁。

验证如下 查看锁的类型,确定是间隙锁

MYSQL进阶_第30张图片

 开启线程B,想在之间插入数据

MYSQL进阶_第31张图片

 进入阻塞状态,需等线程A释放间隙锁才可。

4、InnoDB引擎 

InnoDB和MyISAM的区别是什么?

1、MyISAM不支持行级锁,在并发条件下表现差

2、MyISAM 不提供事务支持。InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别,具有提交(commit)和回滚(rollback)事务的能力。并且,InnoDB 默认使用的 REPEATABLE-READ(可重读)隔离级别是可以解决幻读问题发生的(基于 MVCC 和 Next-Key Lock)。

3、MyISAM不支持外键。外键对于维护数据一致性非常有帮助,但是对性能有一定的损耗。因此,通常情况下,我们是不建议在实际生产项目中使用外键的,在业务代码中进行约束即可!

MYSQL进阶_第32张图片

4.是否支持数据库异常崩溃后的安全恢复

MyISAM 不支持,而 InnoDB 支持。

使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log

5.是否支持 MVCC

MyISAM 不支持,而 InnoDB 支持。

讲真,这个对比有点废话,毕竟 MyISAM 连行级锁都不支持。MVCC 可以看作是行级锁的一个升级,可以有效减少加锁操作,提高性能

6.索引实现不一样。

MyISAM中的索引方案_myisam的索引结构_glenshappy的博客-CSDN博客

MyISAM索引的原理

见MyISAM中的索引方案_myisam的索引结构_glenshappy的博客-CSDN博客

4.1 逻辑存储结构

MYSQL进阶_第33张图片

表空间:一个mysql实例可以对应多个表空间,用于存储记录、索引等数据

段:分为数据段,索引段、回滚段,InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段即为B+树的非叶子节点。段用来管理多个区。

区:表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16k,即一个区中有64个连续的页。

页,是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16kb。为了保证页的连续性,InnoDB的存储引擎每次从磁盘申请4-5个区。 

4.2 InnoDB引擎 内存结构

4.2.1 缓冲池 

MYSQL进阶_第34张图片

 4.2.2 更改缓冲区

MYSQL进阶_第35张图片

 4.2.3 自适应哈希索引

MYSQL进阶_第36张图片

 4.2.4 日志缓冲区

MYSQL进阶_第37张图片

 4.3 InnoDB磁盘结构

MYSQL进阶_第38张图片

 ​​​​​MYSQL进阶_第39张图片

 MYSQL进阶_第40张图片

 4.4 后台线程

MYSQL进阶_第41张图片

整体流程概述:

当数据库进行业务操作时,会直接操作缓冲区,缓冲区倘若没有数据,会从磁盘中读入至缓冲区中。缓冲区的数据会以一定时机,频率刷新到磁盘当中,在磁盘当中永久化的保存下来。

MYSQL进阶_第42张图片

4.3 事务原理

4.3.1 Redolog

重做日志,记录的是事务提交时数据页的物理修改,用来实现事务的持久性。

该日志文件由两部分组成:重做日志缓冲(redo log buffer) 以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都保存到日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用。

脏页:缓冲区的数据变更,而还未写入磁盘,称为脏页

当脏页刷新到磁盘发生错误时,可以通过Redolog进行恢复

MYSQL进阶_第43张图片

4.3.2 undolog

回滚日志,用于记录数据被修改前的信息,用于事务回滚操作 ,作用包含两个:提供回滚和MVCC(多版本并发控制)

MYSQL进阶_第44张图片

 4.4 MVCC

4.4.1 MVCC基本概念

当前读;

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如

 快照读:

简单的select(不加锁)就是快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。

MYSQL进阶_第45张图片

开启Repeated Read 后,后面的select访问的都是第一个select的版本

不可重复读指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况。 

 当前读和快照读,以及他们的区别:

当前读和快照读 - 墨天轮

MVCC :

多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MYSQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log 日志,readView.

4.4.2 MVCC实现原理--undolog版本链在事务中的体现 

记录中的隐藏字段

MYSQL进阶_第46张图片

 例如事务2、3、4、5开启,当事务2进行了修改操作时,形成undolog版本链如下所示

MYSQL进阶_第47张图片

当事务3进行了修改操作,版本链更新,成如图所示

MYSQL进阶_第48张图片

 当事务4开始后,再次更新版本链,如图所示

MYSQL进阶_第49张图片

 4.4.3 readView介绍

readView

ReadView(读视图)是快照读SQL执行时MVCC提取数据的依据,记录并维护当前活跃的事务(未提交的)id

ReadView中包含了四个核心字段

MYSQL进阶_第50张图片

MYSQL进阶_第51张图片

不同隔离级别,生成的ReadView的时机不同

在RC级别下,在事务中每一次执行快照时生成ReadView

MYSQL进阶_第52张图片

 那么,如何去判定事务4中查询的是哪个历史版本的数据呢?

根据之前的规则,并且按照版本链从4倒回去找,直到找到符合规则的历史版本数据,可以找到

 

 这个符合规则,那么事务4的快照读查询到的便是事务2修改后的记录。

在RR级别下,仅在事务第一次执行快照读时生成ReadView,后续重复用ReadView

MYSQL进阶_第53张图片

你可能感兴趣的:(java,数据库,服务器)