1.查询语句
mysql> select * from T where ID=10;
大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。
Server 层:包括连接器、查询缓存、分析器、优化器、执行器
存储引擎层:负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。
不同的存储引擎共用一个Server 层。
连接器:
负责跟客户端建立连接、获取权限、维持和管理连接。 命令 show processlist 查看建立的连接状况
查询缓存
之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。但是大多数情况下建议不要使用查询缓存,为什么呢?因为查询缓存往往弊大于利。
查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。
query_cache_type 设置成 DEMAND,这样对于默认的 SQL 语句都不使用查询缓存。MySQL 8.0 版本直接将查询缓存的整块功能删掉了。
分析器
“词法分析:”MySQL 需要识别出里面的字符串分别是什么,代表什么
“语法分析”:根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法
优化器
表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。
执行器
先判断一下你对这个表 T 有没有执行查询的权限
1.调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中;
2.调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
3.执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
慢查询日志中看到一个 rows_examined 的字段,表示这个语句执行过程中扫描了多少行。在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相的。
2.更新语句
mysql> update T set c=c+1 where ID=2;
更新流程涉及两个重要的日志模块:redo log(重做日志)和 binlog(归档日志)
重要的日志模块:redo log
WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。
crash-safe:即使数据库发生异常重启,之前提交的记录都不会丢失
重要的日志模块:binlog
InnoDB 引擎在执行这个简单的 update 语句时的部流程
将 redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"