MySQL的逻辑架构图,基于5.7版本,8.0的版本去除了查询缓存。
大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。
Server层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5版本开始成为了默认存储引擎。
也就是说,你执行 create table 建表的时候,如果不指定引擎类型,默认使用的就是 InnoDB。不过,你也可以通过指定存储引擎的类型来选择别的引擎,比如在 create table 语句中使用engine=memory
来指定使用内存引擎创建表。不同存储引擎的表数据存取方式不同,支持的功能也不同。
以下从5步进行说明一条 SQL 的执行流程。
我们的程序或者工具要操作数据库,第一步要做什么事情?
跟数据库建立连接。
作用:管理连接,权限验证
MySQL服务监听的端口默认是3306,客户端连接服务端的方式有很多。
可以是同步的也可以是异步的,可以是长连接也可以是短连接,可以是 TCP 也可以是 Unix Socket, MySQL 有专门处理连接的模块,连接的时候需要验证权限。
我们怎么查看MySQL当前有多少个连接?
可以用show status
命令,模糊匹配Thread
show global status like 'Thread%';
字段 | 含义 |
---|---|
Threads cached | 缓存中的线程连接数。. |
Threads connected | 当前打开的连接数。 |
Threads created | 为处理连接创建的线程数。 |
Threads running | 非睡眠状态的连接数,通常指并发连接数: |
Threadpool_idle_threads | 线程池空闲线程,8.0中有。 |
Threadpool_threads | 线程池,8.0中有。 |
客户端每产生一个连接或者一个会话,在服务端就会创建一个线程来处理。反过来, 如果要杀死会话,就是Kill线程。
既然是分配线程的话,保持连接肯定会消耗服务端的资源。MySQL 会把那些长时间 不活动的(SLEEP)连接自动断开。
这一步主要做的事情是对语句基于SQL语法进行词法和语法分析和语义的解析。
词法分析就是把一个完整的SQL语句打碎成一个个的单词。
比如一个简单的SQL语句:
select name from user where id = 1;
它会打碎成8个符号,每个符号是什么类型,从哪里开始到哪里结束。
语法分析会对SQL做一些语法检查,比如单引号有没有闭合, 然后根据MySQL定义的语法规则,根据SQL语句生成一个数据结构。
问题:如果我写了一个词法和语法都正确的SQL,但是表名或者字段不存在,会在 哪里报错?是在数据库的执行层还是解析器?比如:
select * from aaaaa;
似乎解析器可以分析语法,但是它怎么知道数据库里面有什么表,表里面有什么字段呢?
实际上还是在解析的时候报错,解析 SQL 的环节里面有个预处理器。
它会检査生成的解析树,解决解析器无法解析的语义。比如,它会检査表和列名是否存在,检査名字和别名,保证没有歧义。
预处理之后得到一个新的解析树。
作用:生成、选择执行路径,索引的选择,Cost(计算成本最低的)
査询优化器的目的就是根据解析树生成不同的执行计划Execution Plan
,然后选 择一种最优的执行计划,MySQL里面使用的是基于开销cost
的优化器,那种执行计划开销最小,就用哪种。
但是优化器也不是万能的,并不是再垃圾的SQL语句都能自动优化,也不是每次都能选择到最优的执行计划,大家在编写SQL语句的时候还是要注意。
优化完之后,得到一个什么东西呢?优化器最终会把解析树变成一个査询执行计划。查询执行计划是一个数据结构。
EXPLAIN
,就可以看到执行计划的信息。EXPLAIN select name fiom user where id=l;
如果要得到详细的信息,还可以用FORMAT=JSON
,或者开启optimizer traceo
-- 会得到一个json数据
EXPLAIN FORMAT=JSON select * from card;
得到执行计划以后,SQL 语句是不是终于可以执行了?
首选要选择存储引擎,利用存储引擎提供的相应的API来完成操作,最后把数据返回给客户端。
不同的存储引擎存放数据的方式不一样,产生的文件也不一样,innodb是1个, memory没有,myisam 是两个。
没有指定的时候,数据库就会使用默认的存储引擎,5.5.5之前,默认的存储引擎是MylSAM, 5.5.5之后,默认的存储引擎是 InnoDB。
MylSAM (3个文件):应用范围比较小。表级锁定限制了读/写的性能,因此在Web和数据仓库配置中,它通常用于只读或以读为主的工作。
特点:
(怎么快速向数据库插入100万条数据?我们有一种先用 MylSAM 插入数据,然后修改存储引擎为 InnoDB 的操作。)
适合:只读之类的数据分析的项目。
InnoDB (2个文件)
mysql 5.7中的默认存储引擎。InnoDB 是一个事务安全(与ACID兼容)的MySQL 存储引擎,它具有提交、回滚和崩溃恢复功能来保护用户数据。InnoDB 行级锁(不升级 为更粗粒度的锁)和 Oracle 风格的一致非锁读提高了多用户并发性和性能。InnoDB 将 用户数据存储在聚集索引中,以减少基于主键的常见查询的I/O。为了保持数据完整性, InnoDB 还支持外键引用完整性约束。
特点:
适合:经常更新的表,存在并发读写或者有事务处理的业务系统。
Memory (1个文件)
将所有数据存储在RAM中,以便在需要快速查找非关键数据的环境中快速访问。这 个引擎以前被称为堆引擎。其使用案例正在减少;InnoDB及其缓冲池内存区域提供了一 种通用、持久的方法来将大部分或所有数据保存在内存中,而 ndbduster 为大型分布式 数据集提供了快速的键值查找。
特点:
不同的存储引擎提供的特性都 不一样,它们有不同的存储机制、索引方式、锁定水平等功能。