MySQL技术内幕与存储引擎①

基本概念

数据库: 文件的集合, 是依照某种数据模型组织起来并存放于二级存储器中的数据集合

数据库实例:程序, 位于用户与操作系统之间的一层数据管理软件, 用户对数据库的任何操作, 包括数据库定义、数据查询、数据维护、数据库运行控制等都是在数据库实例下运行的, 应用程序只有通过数据库实例才能和数据库打交道

image.png

连接MySQL

TCP/IP

1
mysql -h127.0.0.1 -u root -p

InnoDB 体系架构

image.png

后台线程的主要作用是负责刷新内存池的数据,保证缓冲池中的内存缓存的是最近的数据。此外将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下,InnoDB 能恢复到正常运行状态。

后台线程

Master Thread

Master Thread 是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性

IO Thread

在InnoDB 存储引擎中大量使用AIO(Async IO) 来处理读写IO 请求,这样可以极大提高数据库的性能

Purge Thread

事务被提交后,其所使用的undolog 可能不再需要,因此需要PurgeThread 来回收已经使用并分配的undo 页。

Page Cleaner Thread

将之前版本中脏页的刷新操作都放入到单独的线程中

内存

缓冲池

InnoDB 存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理,在数据库系统中,由于CPU 速度与磁盘速度之间的鸿沟,基于磁盘的数据库系统通常使用缓冲池技术来提高数据库的整体性能。

在数据库中进行读取页的操作,首先将从磁盘读到的页放在缓冲池中,这个过程称为将页“FIX” 在缓冲池,下一次再读相同的页时,该页在缓冲池中被命中,直接读取该页,否则读取磁盘上的页。

在数据库中修改页的操作,则首先修改缓冲池的页,然后再以一定频率刷新到磁盘上。

image.png

文件

  • 参数文件:配置参数,用来寻找数据库各种文件所在位置以及指定某些初始化参数,,my.cnf

    • 什么是参数:可以把数据库参数看成一个键值对
    • 参数类型:动态参数和静态参数
  • 日志文件:记录MySQL 实例对某种条件作出响应时写入的文件,如错误日志、查询日志等等

    • 错误日志:对MySQL 的启动、运行、关闭过程进行了记录
    • 慢查询日志:将运行时间超过指定阀值的所有SQL 语句都记录到慢查询日志文件中,默认是10秒
    • 查询日志:记录所有对MySQL 数据库请求的信息,无论这些请求是否得到了执行
    • 二进制文件:记录了对MySQL 数据库执行更改的所有操作
  • socket 文件:使用UNIX 域套接字方式进行连接时需要的文件
  • pid 文件:MySQL 实例的进程ID 文件
  • MySQL 表结构文件:用来存放MySQL 表结构定义文件
  • 存储引擎文件

索引组织表

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

在InnoDB 存储引擎表中,每张表都有一个主键(Primary key),如果在创建表时没有显式地定义主键,那么InnoDB 存储引擎会按如下方式选择或者创建主键:

  • 首先判断表中是否有非空的唯一索引,如果有,则该列为主键(选择第一个被定义的非空唯一索引)
  • 如果不符合上述条件,InnoDB 存储引擎将选择表时第一个定义的非空唯一索引为主键。

InnoDB 逻辑存储结构

image.png

表空间: 表空间可以看做是InnoDB 存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。

段: 表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等等。

InnoDB 存储引擎表是索引组织的,因此数据即索引,那么数据段即为B+树的叶子节点(Leaf node segment)

索引段即为B+树的非索引节点(Non-leaf node segment)

是由连续页组成的空间,在任何情况下,每个区的大小都为1 MB,在默认情况下,InnoDB 存储引擎页的大小为16KB,即一个区中一共有16 个连续的页。

是InnoDB 磁盘管理的最小单位,在InnoDB 存储引擎中,默认每个页的大小为16KB

在InnoDB 存储引擎中,常见的页类型有:

  • 数据页
  • undo 页
  • 系统页
  • 事务数据页
  • 插入缓冲位图页
  • 插入缓冲空闲列表页
  • 未压缩的二进制大对象页
  • 压缩的二进制大对象页

数据页存放的是完整的每行的记录

非数据页的索引页,存放的是键值及指向数据页的偏移量

:InnoDB 存储引擎,数据是按行进行存放的

InnoDB 行记录格式

InnoDB 存储引擎提供了Compact 和Redundant 两种格式来存放行记录数据

Compact 行记录格式

代办

索引与算法

InnoDB 存储引擎支持

  • B+ 树索引
  • 全文索引
  • 哈希索引

B+ 树索引并不能找到一个给定键值的具体行,B+树索引能找到的只是被查找数据行的所在的页,然数据库通过把页读到内存,再从内存中进行查找,最后得到要查找的数据。

image.png

聚集索引

聚集索引是按照每张表的主键构造一课B+ 树,同时叶子节点存放的就是整张表的行记录数据,也将聚集索引的叶子节点成为数据页

聚集索引的存储并不是物理上连续,而是逻辑上连续

非聚集索引

对于非聚集索引,叶子节点并不包含记录的全部数据,叶子节点除了包含键值对以外,每个叶子节点的索引行还包括一个书签,这个书签用来告诉InnoDB 引擎哪里可以找到与索引对应的行数据,由于InnoDB 存储引擎表是索引组织表,因此InnoDB 存储引擎的辅助索引的书签就是相应的行数据的聚集索引键

聚集索引和非聚集索引的关系

非聚集索引的存在并不影响聚集索引的组织,因此每张表上可以有多个辅助索引。当通过非聚集索引来寻找数据的时候,InnoDB 存储引擎会遍历非聚集索引并通过叶级别的指针获得指向主键索引的主键,然后再通过主键索引来找到一个完整的行记录。

image.png

Cardinality 值

什么时候添加B+ 树索引会比较合适

对于列值具有高选择性的添加索引会有意义

高选择性是某个字段选取的值范围很广,几乎没有重复

如何查看索引是否是高选择性

可以通过SHOW INDEX 的结果中的Cardinality 值来观察

什么是Cardinality 值

Cardinality 值是一个预估值,表示索引中不重复记录数量的预估值

在实际应用中,Cardinality / n_rows_in_table 需要非常接近1,在访问高选择性属性的字段并从表中取出很少一部分数据的时候,对这个字段添加B+ 树索引是非常必要的。

InnoDB 是如何统计Cardinality

在InnoDB 存储引擎中,Cardinality 统计信息的更新发生在两个操作中:INSERT and UPDATE。

如果一张表有50GB 的数据,那么统计一次Cardinality 会耗费非常多的时间,这样会增加数据库的负荷,因此,InnoDB 存储引擎内部对更新Cardinality 信息的策略是:

  • 表中1/16 的数据已经发生过了变化
  • stat_modified_counter > 2 000 000 000 (stat_modified_counter 是数据发生变化的次数)

lock and latch

latch 一般称之为轻量级的锁,其要求上锁的时间必须是非常短的,在InnoDB 存储引擎中,latch 又分为mutex 互斥锁和relock 读写锁,其目的都是用来保证并发线程操作临界资源的正确性。

lock 的对象一般是事务,用来锁定数据库中的对象,如表、页、行。一般lock 的对象是在事务commit 或者rollback 后进行释放。

InnoDB 存储引擎中的锁

锁lock 的类型

InnoDB 存储引擎实现了如下两种标准的行级锁:

  • 共享锁S Lock: 允许事务读一行数据
  • 排他锁X Lock: 允许事务删除或者更新一行数据

一致性非锁定读

一致性非锁定读是指如果读取的行被加了X 锁,这时候读操作并不会等待行锁的释放,而是去读取行的快照,行的快照指的是该行之前版本的数据,该实现是通过undo 段来完成的,而undo 用来在事务中回滚数据的,读取快照数据也不需要上锁,因为没有事务需要对历史数据进行操作。

一致性锁定读

死锁

死锁避免

  • 超时: 两个事务互相等待,当其中一个事务的等待时间超过了阈值,事务就会进行回滚,另一个等待的事务就会继续进行下去。
  • wait-for graph (等待图)

事务

ACID

  • 原子性:要么做,要么都不做
  • 一致性:指的是事务将数据库从一种状态转移到下一种一致状态
  • 隔离性:每个读写操作的事务对其它事务的操作不影响
  • 持久性:事务一旦提交,其结果就是永久性的

事务的实现

redo

重做日志用来实现事务的持久性,即ACID 中的D,其由两部分组成,一是内存中的重做日志缓存,二是重做日志文件

重做日志在InnoDB 中是由两部分组成的:redo log和undo log, redo log保证事务的持久性,undo log 用来帮助事务回滚及MVCC 的功能

为了确保每次日志都写入了重做日志文件,在每次将重做日志缓冲写入到重做日志文件后,InnoDB 存储引擎都将调用一次fsync 操作

重做日志记录了事务的行为,可以很好地通过其对页进行重做操作

undo

事务的回滚,需要用到undo 的信息将数据回滚到修改之前的样子。

本文标题:MySQL技术内幕与存储引擎①

文章作者:Enda Lin

发布时间:2019年07月24日 - 11:20

最后更新:2019年11月07日 - 10:21

原始链接:https://wt-git-repository.github.io/2019/07/24/MySQL技术内幕与存储引擎①/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。