MySQL听讲(一)——流程

本文从宏观角度分析mysql 组成及其功能。

公共操作流程

一条sql 语句(包括查询和更新)是怎样执行的呢,大致经过如下图所示,下面我来简单分析一下这几个过程:

《MySQL听讲(一)——流程》 MySQL执行流程.png

连接器

首先,你需要登录到mysql 上,常用命令为mysql -h 主机IP -u 用户名 -p 密码,此处严格区分大小写。

从mysql 5.7开始,默认连接时间为8小时,也就是说8小时内没有请求,连接会断开,这也是很多开发者经常遇见过了一夜,服务器上抛了好多错,mysql 服务器断开连接了的原因,抛错Lost connection to MySQL server during query。解决这个问题可以使用以下方式:

  1. 长连接:指连接成功后,如果客户端持有请求,则一直使用同一个连接。
  2. 短连接:指每次连接都会创建一个新的连接,执行很少的使用此处后会断开连接。

常用的长短连接sql为:select 1.(表示从哑表dual查询1)

在某些失误情况下,你的操作可能会导致锁表,此时执行show processlist显示所有MySQL连接,然后kill ID切掉对应的连接。该命令还可以查看所有MySQL线程的状态,其中sleep表示空闲状态。

查询缓存

当有查询语句进入时,会先进入查询缓存,没有瞄中才会走下面的流程。其中查询语句为key ,结果为value
但这部分比较鸡肋,因为如果某张表有一条增删改操作,则该表的查询缓存会被清空。外加redis 近来的流行,该部分在8.0版本被删除。

通过show variables like 'query_cache_type';语句来查看当前该变量状态。默认为OFF,通过参数query_cache_type设置为ON来开启。

分析器

该组件会进行词法分析和语法分析。

词法分析,包含关键字分析和字符转换。关键字分析,从select 知道这是一个查询,知道from 后面是表名。字符转换,比如将字符“id”转换为字段id,将字符“T”转换为表T。
语法分析,分析语句的正确性。比如第一个单词必须为增删改查中的一个,如果是select,后面要有查询字段,from 紧随其后等等。

在这个阶段常见的错误有:
常见的未知字段错误
[1054] Unknown column 'xx' in 'field list'
同理,还有表未知错误。
[1146] Table 'test.user1' doesn't exist

优化器

优化器会根据你的sql来选择使用哪个索引,其依据是选择这个索引总体效率会更高,包括数量、回表、排序等都在考虑中。

执行器

在执行器中,会首先检查你有没有可以操作这个表的权限。如果有,就继续执行。根据表的引擎定义,去使用相关的引擎接口。
在执行的过程中,对于优化器认为没有索引的,会逐行进行扫描,直到最后一行。而优化器认为有索引的会扫描相关行,比如扫描id>10的,因为索引一般都是B+树的,有一定顺序,会扫描id=10,并返回其之后的。

权限之所以放在这个阶段因为触发器、视图、存储过程的权限只有执行阶段才可以确定是否拥有其执行权限。

更新操作追加

对于更新操作,从执行器以后会有日志部分,一下是针对于id=1这一行数据的name修改为‘xxx’:

《MySQL听讲(一)——流程》 更新日志流程.png

可以看到MySQL+InnoDB使用的是二阶段提交的策略,为的就是保证备份日志(bin log)和读写日志(redo log)一致。

故障:1)如果redo log进入prepare状态,bin log未写入,MySQL崩溃了,怎么办?
答:崩溃恢复时,redo log会回滚事务。
2)执行到bin log写完了,MySQL崩溃了,怎么办?
答:如果redo log事务是完整的,即有commit标识,崩溃恢复,直接提交;
如果redo log中事务是不完整的,即只有prepare状态,则判断对应事务的bin log是否存在且完整:是,提交事务;否,回滚事务。

其中redo log和bin log是通过一个共同的数据字段关联的,XID。

bin log和redo log的区别

bin logredo log
所属区域执行器存储引擎
日志类型逻辑日志
记录这个语句的原始逻辑
物理日志
记录“在某个数据页上做的什么修改”
写入方式追加写入
增加文件
循环写入
空间固定
作用恢复数据
备份数据
存储数据
读写数据

删除的流程

比如有一张表,主键为3,4,6,7等。需要删除id=4的数据,InnoDB引擎会把id=4的数据标记为删除。在下次要插入id5的数据时,会复用这块地方。这也就是删除了数据后,磁盘并不会缩小和磁盘复用的原理。同理适用于数据页。

对于插入和删除,都会出现“空洞”。即可以复用但是没有用起来的空间。
修复空洞的方法是重建表。你可以使用alter table A engine=InnoDB;重建表A。这个过程叫“Online DDL”。
具体内部过程为:
1)建一临时文件,扫描表A主键的所有数据页;
2)用数据页中表A的记录生产B+Tree,存到临时文件中;
3)执行的过程中,对表A的操作记录到一个日志文件中(row log);
4)临时文件生成完毕,将日志文件写到临时文件中,此时逻辑上临时文件与表A的数据相同;
5)用临时文件替换表A的数据文件。

在此期间,禁止执行修改该表元数据。整个过程有MDL锁(alter时拿MDL写锁,复制数据时拿MDL读锁)。
因为整个过程都是在InnoDB内部完成的,所以需要注意磁盘大小。

    原文作者:靈08_1024
    原文地址: https://www.jianshu.com/p/ecfbfa77deac
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞