本篇内容包括:MySQL 简介、MySQL的逻辑架构以及MySQL 语句执行流程
一、MySQL 简介
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型和大型网站的开发都选择 MySQL 作为网站数据库。
二、MySQL的逻辑架构
MySQL 的逻辑架构大致可以分为三层:客户端、Server层、存储引擎层
- 第一层:客户端(服务器层):主要做连接处理、授权认证、安全保障等等;
- 第二层:Server 层,涵盖了 MySQL 大多数核心服务功能,包括查询解析、分析、优化、缓存以及所有内置函数(例如:日期,时间,数学和加密函数等)。存储过程,触发器,视图等跨存储引擎的功能也都在这一层实现。
Server 层基本组件:
- 连接器:我们使用数据库,第一步是连接到数据库。而连接器负责跟客户端建立连接、获取权限、维持和管理连接
- 查询缓存:执行查询语句的时候,会先查询缓存,校验 SQL 是否执行过,如果有 SQL 的缓存,直接返回给客户端,如果没有命中,执行后续的操作;(MySQL 8.0 版本删除)
- 分析器:没有命中缓存的话,SQL 语句就会经过分析器,主要分为两步,词法分析和语法分析,先看 SQL 语句要做什么,再检查 SQL 语句语法是否正确;
- 优化器:优化器对查询进行优化,包括重写查询、决定表的读写顺序以及选择合适的索引等,生成执行计划,优化器主要做的操作包括:
- 表里面有多个索引的时候,决定使用哪个索引;
- 一个语句有多表关联(join)的时候,决定各个表的连接顺序;
- 执行器:首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会根据执行计划去调用引擎的接口,返回结果。
- 存储引擎层:主要负责数据的存储和提取,Server层通过 API 与存储引擎层进行交互。服务器通过 API 与存储引擎通信,这些接口屏蔽了不同存储引擎的差异,使得差异对上层查询过程透明。除了会解析外键定义的 InnoDB 外,存储引擎不会解析 SQL,不同存储引擎之间也不会相互通信,只是简单响应上层服务器请求。
三、MySQL 语句执行流程
1、查询语句执行过程
查询语句的执行流程如下:权限校验、查询缓存、分析器、优化器、权限校验、执行器、引擎。
举个例子,查询语句如下:
代码语言:javascript复制select * from user where id > 1 and name = 'Benjamin';
- 首先检查权限,没有权限则返回错误;
- 若开启了缓存,会检查缓存是否有该 sql 对应结果(缓存存储形式key-vlaue,key是执行的sql,value是对应的值)若开启缓存又有该 sql 的映射,将结果直接返回;
- 词法分析和语法分析。提取表名、查询条件,检查语法是否有错误;
- 两种执行方案,先查 id > 1 还是 name = ‘Benjamin’,优化器会生成执行计划、选择索引等操作,选取最优执行方案;
- 然后来到执行器,打开表调用存储引擎接口,逐行判断是否满足查询条件,满足放到结果集,最终返回给客户端;若用到索引,筛选行也会根据索引筛选。
2、更新语句执行过程
更新语句执行流程如下:分析器、权限校验、执行器、引擎、redo log(prepare状态)、binlog、redo log(commit状态)
举个例子,更新语句如下:
代码语言:javascript复制update user set name = 'Benjamin' where id = 1;
- 先查询到 id 为1的记录,有缓存会使用缓存。
- 拿到查询结果,将 name 更新为
'Benjamin'
,然后调用引擎接口,写入更新数据,innodb 引擎将数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态。 - 执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为commit状态。
- 更新完成。
为什么记录完 redo log,不直接提交,而是先进入 prepare状 态?
假设先写 redo log 直接提交,然后写 binlog,写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 binlog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。