目录

MySQL组成模块

  • 连接器:客户端通过驱动连接,连接器负责进行连接交互
  • 查询缓存:针对查询语句的缓存,只有查询语句完全一致时,才能命中,8.0以移除
  • SQL解析器:将SQL语句解析成语法树
  • 预处理模块:检查查询字段和表是否存在,还有扩展查询时*为全部字段
  • 优化器:根据代价选择一种执行代价最低的路径,比如存在多个索引时,选择使用哪个索引
  • 执行器:与存储引擎交互,将执行计划交给存储引擎

MySQL存储基础

MySQL数据文件存储位置

1
SHOW VARIABLES LIKE 'datadir';

这个目录下会为每个数据库创建一个目录,目录下有这几种文件

  • *.frm文件:表结构文件,存储表结构定义
  • *.ibd文件:表数据文件,每张表一个单独的ibd文件
  • *.opt文件:存储当前数据库默认字符集和字符校验规则

MySQL表空间的结构

表空间由:段、区、页、行组成 https://cdn.jsdelivr.net/gh/hts0000/images/202302231621037.png

行就是表中的一行数据,表结构不同,行存储也有不同的存储结构。

页是存储引擎操作的最小单位,默认大小为16KB,从硬盘读取或写入硬盘都是以16KB的大小进行操作的,这是为了降低磁盘I/O。页的类型有很多种,数据页、Undo页等,数据存储在数据页中。

区由64个页组成,大小1MB。页还是太小了,数据很容易存储在不同的页中,造成随机I/O。因此数据量大的时候,会使用区来分配,这样可以使得多个页是顺序存储的。

段由多个区组成,表空间由多个段组成。

MySQL行格式

行格式指示了一行数据如何组织和记录的。下面是COMPACT行格式的组织形式。行格式将一条数据分为额外记录信息和真是数据两部分。 https://cdn.jsdelivr.net/gh/hts0000/images/202302231649778.png

变长字段长度列表 记录每一个类型为varchar的列的字节长度。比如存储了一个字符,而且字符集为ascii,那么字节长度为1。如果有多个类型为varchar的列,他们的存放顺序是逆序的。当不存在varchar类型的列时,变长字段长度列表不存在。

NULL值列表 以一个8bit的数,来标识那个列可以为NULL,可以为NULL的列置为1,少于8列,也是8bit,多余8列,再往上补8bit。NULL值列表的位,也是逆序存储的。当没有允许为NULL的列时,NULL值列表这个额外字段不存在。

行溢出

当一行的数据大于一页的存储空间16KB时,会发生行溢出。溢出有两种处理方式:

  • 将溢出的部分移到溢出页,未溢出的部分后面记录一个指针,指向溢出页的位置。
  • 真实数据只存储指向溢出页的指针,所有数据都存储在溢出页。

索引

索引分类

我们可以按照四个角度来分类索引。

  • 按「数据结构」分类:B+tree索引、Hash索引、Full-text索引。
  • 按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)。
  • 按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引。
  • 按「字段个数」分类:单列索引、联合索引。

MySQL常见面试题

索引底层使用了什么数据结构和算法?

为什么 MySQL InnoDB 选择 B+tree 作为索引的数据结构?

什么时候适用索引?

什么时候不需要创建索引?

什么情况下索引会失效?

有什么优化索引的方法?

基于GTID搭建数据库主从

GTID同步原理

GTID(Global Transaction ID)全局事务ID。主库每一个事务产生一个全局唯一的GTID号,连同变更记录一同写入到bin-log日志中,从库的io线程拉取主库变更的bin-log日志,同步到本地的relay-log日志中,sql线程读取relay-log日志内的GTID号,对比本地的bin-log日志内的GTID,查看是否执行过该GTID号代表的事务,如果没有,将变更内容写入数据库,如果有则忽略。

GTID同步对比bin-log日志同步

实操