我是靠谱客的博主 甜美裙子,最近开发中收集的这篇文章主要介绍Mysql架构体系深入剖析学习 Mysql 架构体系拆解、设计剖析 Mysql 存储引擎(最常用InnoDB为例) 原理拆解、设计剖析Mysql 事务实现 原理拆解、设计剖析Mysql 锁实现 原理拆解、设计剖析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

 Mysql 架构体系拆解、设计剖析 

页的数据结构

页内记录维护

顺序保证

插入策略

页内查询

Mysql 存储引擎(最常用InnoDB为例) 原理拆解、设计剖析

InnoDB内存管理宗旨 

LRU内存淘汰算法

Mysql 事务实现 原理拆解、设计剖析

Mysql事务基本概念

事务特性ACID

并发问题

隔离级别

         Mysql事务实现机制

Mysql InnoDB 事务管理机制  ------- MVCC

undo log   事务回滚

redo log   事务固化

Mysql 锁实现 原理拆解、设计剖析

InnoDB锁种类

InnoDB加锁过程


 Mysql 架构体系拆解、设计剖析 

Mysql数据都是 以页(page)为单位 去做内外层交换或者刷新取数的,所以页是怎么划分,怎么管理的呢?

页的数据结构

页头:主要记录页的左右兄弟页面指针,还记录页面空间使用情况。(页面的控制信息,共占56个字节)。页头是双向指针。

虚记录:最小虚记录比页内最小主键还小;最大虚记录比业内最大主键还大。谈到mysql主键,就是聚簇索引,聚簇索引又是什么呢,数据结构和数存在一起

记录堆:行记录存储区,包括有效记录和已删除记录两种

自由空间链表:把被删除的记录链接起来的链表,为了方便找到被删除的记录,清理,节约空间

 未分配空间:页面未使用的空间

页尾:占8个字节,存储页面的校验信息

页内记录维护

Mysql InnoDB用 聚簇索引做主键索引。主键索引为B+ Tree。聚簇索引是Data和索引存在一起,根据索引的key得到一行记录,Data是按照索引的结构有序存储的。

  • 顺序保证

Mysql的顺序保证 选用的是 逻辑有序。逻辑有序就是 每次一条新数据都给个指针去指向相邻的数据,这样的话插入就很快,但是读取数据时因为是乱序,无法用二分法查找,得遍历查找,所以涉及到后面的页内查询的方法。所以逻辑有序就是页内通过一条单向链表把数据链接起来。 物理有序,就是每次插入时,已有数据都要按需求移动位置,但是查询的时候因为是按顺序放的,所以二分查询的话就会比较快。 所以,逻辑有序就是写的快,读的慢,物理有序就是 写的慢,读的快。

所以,Mysql的顺序保证就是1.页内通过一条单向链表来把数据连接起来 2.页与页之间通过 页头双向指针 联系起来。

  • 插入策略

插入的空间有两个选择,自由空间链表和未使用空间。Mysql优先使用自由空间链表,充分利用空间来存储有效数据,MongoDB偷懒,拿到一块用一块,不管不顾。Mysql同样也需要定期清理空间,因为删除记录会残留碎片。 

  • 页内查询

页内查询,逻辑有序用遍历,物理有序用二分查找。但是二分查找的话,因为每条记录是不一样的大小,所以不能根据size去二分查找。所以不论是逻辑有序还是物理有序都不可以用二分查找。 

所以有了 SLOT 槽。根据页内设置槽的数量和大小,每个slot指向一个记录。Slot是一堆连续的内存,把整个链表根据slot数量拆分为多个sub-list。每个slot指向一个记录即每个sub-list的头 。Slot同来帮助我们实现一个近似的二分查找。

Mysql的页内查询就是 用Slot来存放分链表,二分查找Slot,锁定部分数据,再对该部分数据进行遍历查找。

Mysql 存储引擎(最常用InnoDB为例) 原理拆解、设计剖析

InnoDB内存管理宗旨 

1.预分配内存管理空间,即设置缓存-------------------------------------------------> 内存池

2.已页为单位加载:如果以记录为单位,粒度太细,IO消耗太大-------------> 内存页面管理:页面映射,页面数据管理

3.内外层空间交换:优先将磁盘里和内存中数据不符的页替换掉,释放内存空间,加载新数据

------------------------------------------------------------------------------------------------->数据淘汰:内存页都被使用;需要加载新数据

LRU算法:在淘汰时,把最长时间没有访问的数据淘汰。每次访问了哪条数据就把那个数据页放在链表头,这样每次链表末尾就是最长时间没有使用的。如果只有一个LRU链表的话,在访问数据量大的表时可能会把整个LRU链表占满,导致之前的热数据全被淘汰。Redis采用的是 访问时间+访问频率 的方式来避免热数据被淘汰。Mysql采用 两层LRU(LRU_new:LRU_old   5:3) 的方式。访问大表时即使把二级LRU占满也没关系,真正的热数据都在一级LRU(LRU_new)。

当访问一条数据要将该数据所在数据页写入内存时,找到free list 找个free page位置放进去,把数据页在磁盘的位置和在内存页的位置记录在 page hash,然后在free list里把该free page干掉,把该已经变成clean page的页插入到LRU list 的 LRU_old的头部,这一步就是页面装载。如果free list显示内存池中没有空闲页了,那么就去找到存放数据页和脏页的 LRU list 开始进行数据淘汰(有疑惑,是什么显示没有空闲页,为什么从LRU list淘汰,LRU list是筛选热数据的放在内存中的,所以LRU list能对应内存池中所有数据吗,不然怎么能判断进入LRU_old的就是冷数据呢),优先对 dirty page进行淘汰,LRU 内存淘汰算法。

LRU内存淘汰算法

LRU 尾部淘汰、LRU Flush淘汰

如果LRU_old里数据都在被使用(dirty page会不会被使用中,这样不会有锁吗),就去Flush Page,选择dirty page进行LRU Flush淘汰。LRU Flush淘汰就是把dirty page从LRU list直接放到Free list去。

OLD---NEW 

innodb_old_blocks_time    old区存货时间大于此值,old区该page才有可能进入new区

new -----old

移动 midpoint 到 LRU old的新Header,保持在5/8位置

为了避免移动次数过多,造成锁,影响并发效率,故只有当 freed_page_clock - 上次移动到Header时free_page_clock  > LRU_new 长度1/4时,即代表发生较多改变了的时候,才移动midpoint。

Mysql 事务实现 原理拆解、设计剖析

Mysql事务基本概念

事务特性ACID

  • A  (Atomicity)原子性:全部成功或者全部失败
  • I      (Isolation)    隔离性:并行事务之间互不干扰
  • D    (Durability)  持久性:事务提交后,永久生效
  • C    (Consistency) 一致性:通过AID保证

并发问题

  • 脏读:读取到未提交数据
  • 不可重复读:两次读取结果不同
  • 幻读:select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。待理解

隔离级别

  • Read Uncommitted(读取未提交内容)  --- 脏读
  • Read Committed(读取提交内容)         --- 不可重复读
  • Repeatable Read (可重复读)        ---幻读。 每次读取相同的结果集,不管其他事务是否提交
  •  Serializable(串行化)                     ---事务排队,隔离级别最高,性能最差 

Mysql事务实现机制

Mysql InnoDB 事务管理机制  ------- MVCC

多版本并发控制

解决 读-写 冲突

隐藏列  transaction_id事务ID   指针ID    全局唯一,事务ID递增,越大代表数据越新

Mysql的读 ------  当前读和快照读

当前读就是读当前存储引擎里的数据,快照读可读创建快照那一刻的历史数据。那么快照读是如何判断当时数据是什么样的呢。

 创建快照的那一刻,保存下当下 活跃事务 的事务ID 到一个列表中,此为 活跃事务ID列表,排序

当开始快照读时,去存储引擎里去寻找数据,找到一条数据,查看其隐藏列中的 tarnsaction id ,如果该条数据 TRX_ID < 活跃事务ID列表中最小TRX_ID,那就直接可见,查看;如果大于活跃事务ID列表中最小TRX_ID,那就去和 活跃事务ID列表中最大TRX_ID  比较 判断,如果大于其,则根据回滚指针指向上一版本数据,如果小于其,判断是否在 活跃事务ID列表 中,如果在,继续根据回退指针指向上一版本数据,如果不在,则 视为可见,查看。

undo log   事务回滚

 

redo log   事务固化

 

 

Mysql 锁实现 原理拆解、设计剖析

InnoDB锁种类

锁粒度:行级锁、间隙锁、表级锁

类型:共享锁(S)、排他锁(X)

 所有  当前读  加 排他锁

select for update

update

delete

凡是要更新的操作,都是 当前读。

  • 行级锁

作用在索引上;聚簇索引 & 二级索引。

聚簇索引------树结构和数据都存在一起。

二级索引:除聚簇索引外都是二级索引,二级索引的data节点存的是主键值

  • 间隙锁

间隙锁,解决 可重复读(RR)  隔离级别下的幻读问题,保证两次当前读操作返回一直的记录。间隙锁,锁的是两条记录之间的GAP。

  • 表级锁

谈到锁是怎么锁的,有四种情况:  唯一索引/非唯一索引  *  RC/RR隔离级别

唯一索引都基本先锁定行,再根据行里涉及到的其他表的索引去锁定其他表的特定行,行级锁。。 

非唯一索引,RC隔离级别 加锁:只涉及行级锁,在两次当前读的情况下,可能出现幻读 现象

非唯一索引,RR隔离级别 加锁:涉及  行级锁 和 间隙锁(GAP锁),所以即使有两次当前读操作也不会改变。

三个间隙锁,锁住那几个范围的值,132,133,135,136,都插不进去的。

间隙锁---------两次当前读之间,其他的事务不会插入新的满足条件的记录。

根据条件查询,无索引可走时

 当没有索引可走时,会 全表扫描  ------------>  表锁

在 RC 已提交读 模式下,会加 表锁 ,然后全部给 Mysql Server,MysqlServer会进行筛选,不符合条件的就释放其锁。

在 RR 可重复读 模式下,会加 表锁+间隙锁,可怕。

避免全表扫描!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

InnoDB加锁过程

锁,是一条一条加的。

死锁的形成:

最后

以上就是甜美裙子为你收集整理的Mysql架构体系深入剖析学习 Mysql 架构体系拆解、设计剖析 Mysql 存储引擎(最常用InnoDB为例) 原理拆解、设计剖析Mysql 事务实现 原理拆解、设计剖析Mysql 锁实现 原理拆解、设计剖析的全部内容,希望文章能够帮你解决Mysql架构体系深入剖析学习 Mysql 架构体系拆解、设计剖析 Mysql 存储引擎(最常用InnoDB为例) 原理拆解、设计剖析Mysql 事务实现 原理拆解、设计剖析Mysql 锁实现 原理拆解、设计剖析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部