Bootstrap

Mysql 知识(mysql 八股文)汇总

这一篇文章分享 mysql 的面试知识,涵盖点比较多。下面我们来从总体到局部来看完 mysql 相关的面试知识。

问:mysql 整体架构是怎么样的?

mysql 整体架构大概可以分为:网络连接层、服务层、存储引擎层和系统文件层。

关于 mysql 官方的架构图如下,虽然经历多个版本迭代,但整体架构还是差不多,mysql 官方地址如下:https://docs.oracle.com/cd/E19078-01/mysql/mysql-refman-5.1/storage-engines.html#figure-storage-engine-architecture:

1)网络连接层

Connectors 组件,是 mysql 向外提供的交互组件,如 java,.net,php 等语言可以通过该组件来操作 SQL 语句,实现与 SQL 的交互。

2)服务层

服务层是 mysql Server 的核心。主要包含系统管理和控制工具、连接池、SQL 接口、解析器、查询优化器和缓存 Cache&Buffer 六个部分。

  • 连接池(Connection Pool):负责存储和管理客户端与数据库的连接,一个线程负责管理一个连接。

  • 系统管理和控制工具(Management Services & Utilities):例如备份恢复、安全管理、集群 管理等

  • SQL 接口(SQL Interface):用于接受客户端发送的各种 SQL 命令,并且返回用户需要查询的结果。

  • 解析器(Parser):负责将请求的 SQL 解析生成一个"解析树"。然后根据一些 mysql 规则进一步检查解析树是否合法。

  • 查询优化器(Optimizer):当“解析树”通过解析器语法检查后,将交由优化器将其转化成执行计划,然后与存储引擎交互。

  • 缓存(Cache&Buffer):缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,权限缓存,引擎缓存等。如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。

3)存储引擎层(Pluggable Storage Engines)

存储引擎负责 MySQL 中数据的存储与提取,与底层系统文件进行交互。MySQL 存储引擎是插件式的,服务器中的查询执行引擎通过接口与存储引擎进行通信,接口屏蔽了不同存储引擎之间的差异 。现在有很多种存储引擎,各有各的特点,最常见的是 MyISAM 和 InnoDB。

4)系统文件层(File System)

该层负责将数据库的数据和日志存储在文件系统之上,并完成与存储引擎的交互,是文件的物理存储层。主要包含日志文件,数据文件,配置文件,pid 文件,socket 文件等。

问:mysql 集群架构

关于 mysql 的架构,最底层的只有主从模式,关于主从模式是简单灵活,能满足多种需求,比较主流的用法,但是写操作高可用需要自己考虑。我们常见还有双主模式,该模式从主从模式演变为双主模式,有双主双写、双主单写两种方式,一般建议使用双主单写。关于主从架构的模式参考下面的图。

问:MySQL 的查询和插入的执行流程

下面我们图解 mysql 一条查询语句是怎么运行的:

  1. mysql 客户端对 mysql server 的监听端口发起请求

  2. 在连接池组件创建连接,分配线程,并验证用户名,密码,库表>权限。

  3. 查询 query_cache,如果有数据直接返回,没有则继续执行。

  4. 通过 sql 接口组件接收 sql 语句,sql 会通过查询分析器分解成数据结构,并且这个结构传递给后续步骤

  5. 查询优化器组件组成查询路径树,并选举一条最优的查询路径。

  6. 调用存储引擎接口,打开表,执行查询,检查存储引擎缓存中是否有对应的缓存记录,如果没有就继续往下执行。

  7. 到磁盘物理文件中寻找数据。

  8. 当查询到所需要的数据之后,先写入存储引擎缓存中,并往 query_cache 写进去。

  9. 返回数据给客户端。

  10. 关闭表。

  11. 关闭线程。

  12. 关闭连接。

mysql 插入的过程如下

  1. mysql 客户端对 mysql server 的监听端口发起请求

  2. 在连接池组件创建连接,分配线程,并验证用户名,密码,库表>权限。

  3. 检查没有问题之后,便进入引擎层开始正式的提交。我们知道 InnoDB 会将数据页缓存至内存中的 buffer pool,所以 insert 语句到了这里并不需要立刻将数据写入磁盘文件中,只需要修改 buffer pool 当中对应的数据页就可以了。

  4. 在开启 redo log 刷盘策略的时候,当 innodb_flush_l

;