逻辑架构
Connectors
1、指不同语言中与 SQL 交互
2、因为 MySQL 是一个网络程序,在 TCP 上定义自己的应用层协议,所以要使用 MySQL,可以编写代码,跟 MySQL Server 建立 TCP 连接,按照其协议进行交互
3、或调用 SDK,比如 Native API、JDBC、PHP 等各语言,或通过 Open Database Connectivity,连接 MySQL,本质上还是在 TCP 连接上通过 MySQL 协议与 MySQL 交互
服务器处理客户端请求
1、MySQL 是 Client / Server 架构,服务器端程序使用 mysqld
2、不论客户端进程、服务器进程是采用哪种方式进行通信,最后实现效果:客户端进程向服务器进程,发送一段文本(SQL 语句),服务器进程处理后,再向客户端进程发送一段文本(处理结果)
3、MySQL Server 结构分三层
(1)第一层:连接层
(2)第二层:服务层
(3)第三层:存储引擎层
4、以下查询查询为例
第一层:连接层
1、系统(客户端)访问 MySQL 服务器前,建立 TCP 连接
2、经过三次握手建立连接成功后, MySQL 服务器对 TCP 传输过来的账号密码做身份认证、权限获取
(1)若用户名或密码错误,客户端收到一个 Access denied for user 错误,客户端程序结束执行
(2)若用户名密码认证通过,服务器会从权限表查出账号拥有的权限与连接关联,之后的权限判断逻辑,都将依赖于此时读到的权限
3、TCP 连接收到请求后,必须要分配给一个线程专门与这个客户端的交互,即线程池,每一个连接从线程池中获取线程,省去了创建和销毁线程的开销
第二层:服务层
1、SQL Interface:SQL 接口
(1)接收用户 SQL 命令,并且返回用户需要查询的结果
(2)MySQL 支持 DML(数据操作语言)、DDL(数据定义语言)、存储过程、视图、触发器、自定义函数等多种 SQL 语言接口
2、Parser:解析器
(1)在解析器中对 SQL 语句进行语法分析、语义分析,将 SQL 语句分解成数据结构,并将这个结构传递到后续步骤,以后 SQL 语句的传递和处理就是基于该结构
(2)如果在分解构成中遇到错误,说明这个 SQL 语句不合理
(3)在 SQL 命令传递到解析器时,被解析器验证和解析,并为其创建语法树,并根据数据字典丰富查询语法树,验证该客户端是否具有执行该查询的权限
(4)创建好语法树后,MySQL 对 SQL 查询进行语法上的优化,进行查询重写
3、Optimizer:查询优化器
(1)SQL 语句在语法解析之后、查询之前,使用查询优化器确定 SQL 语句的执行路径,生成一个执行计划
(2)执行计划表明,使用哪种索引(全表检索 / 索引检索)进行查询 ,和表之间的连接顺序
(3)最后按照执行计划中的步骤,调用存储引擎提供的方法来真正的执行查询,并将查询结果返回给用户
(4)查询策略:选取-投影-连接
4、Caches & Buffers:查询缓存组件
(1)MySQL 内部维持着一些 Cache 和 Buffer,如果能够在其中找到对应的查询结果,那么就不必再进行查询解析、优化、执行的整个过程,直接将结果反馈给客户端
(2)缓存机制是由一系列小缓存组成的。比如:表缓存,记录缓存,key 缓存,权限缓存等
(3)查询缓存可以在不同客户端之间共享
(4)从 MySQL 5.7.20 开始,不推荐使用查询缓存,并在 MySQL 8.0 中删除
第三层
1、引擎层
(1)插件式存储引擎层(Storage Engines):真正负责 MySQL 中数据的存储和提取,对物理服务器级别维护的底层数据执行操作,服务器通过 API 与存储引擎进行通信
(2)不同的存储引擎具有的功能不同
2、存储层
(1)所有数据、数据库、表的定义,表的每一行的内容、索引,都是存在文件系统上,以文件方式存在,并完成与存储引擎的交互
(2)InnoDB 支持不使用文件系统直接管理裸设备,在文件系统之下,可以使用本地磁盘、DAS、NAS、SAN 等各种存储系统,使得不需要直接管理裸设备
MySQL 查询流程
1、查询缓存
(1)Server 如果在查询缓存中发现该 SQL 语句,直接将结果返回给客户端;如果没有,进入到解析器阶段
(2)查询缓存往往效率不高,所以在 MySQL 8.0 之后就抛弃这个功能
(3)在 MySQL 中的查询缓存,不是缓存查询计划,而是查询对应结果,即查询匹配的健壮性大大降低 ,只有相同的查询操作才会命中查询缓存
(4)两个查询请求在任何字符上的不同(例如:空格、注释、大小写),都会导致缓存不会命中,因此 MySQL 查询缓存命中率不高
(5)如果查询请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如 mysql、information_schema、 performance_schema 数据库中的表,则该请求不会被缓存
(6)缓存失效:MySQL 缓存系统会监测涉及到的每张表,只要该表的结构或者数据被修改,如对该表使用 INSERT、UPDATE、DELETE、TRUNCATE TABLE、ALTER TABLE、DROP TABLE、DROP DATABASE 语句,则使用该表的所有高速缓存查询都将无效,并从高速缓存中删除,对 更新压力大的数据库,查询缓存的命中率会非常低
2、解析器
(1)在解析器中对 SQL 语句进行语法分析、语义分析
(2)词法分析:输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么
(3)语法分析:根据词法分析的结果,语法分析器(比如:Bison)会根据语法规则,判断输入的 SQL 语句是否满足 MySQL 语法
(4)如果 SQL 语句正确,则会生成一个语法树
3、优化器
(1)在优化器中会确定 SQL 语句的执行路径,比如是根据全表检索,还是根据索引检索等
(2)在查询优化器中,可以分为逻辑查询优化阶段,和物理查询优化阶段
(3)优化器分析不同执行顺序产生的性能消耗不同,而动态调整执行顺序
4、执行器
(1)在执行之前需要判断该用户是否具备权限
(2)如果没有,就会返回权限错误;如果具备权限,就执行 SQL 查询并返回结果
(3)在 MySQL 8.0 以下版本,如果设置查询缓存,将查询结果进行缓存
Oracle 中的 SQL 执行流程
1、语法检查:检查 SQL 拼写是否正确,如果不正确,Oracle 报语法错误
2、语义检查:检查 SQL 中的访问对象是否存在
3、权限检查:查看用户是否具备访问该数据的权限
4、共享池检查
(1)共享池(Shared Pool):内存池,最主要作用是缓存 SQL 语句和该语句的执行计划
(2)Oracle 通过检查共享池是否存在 SQL 语句的执行计划,来判断进行软解析,还是硬解析
(3)在共享池中,Oracle 首先对 SQL 语句进行 Hash 运算 ,然后根据 Hash 值在库缓存(Library Cache)中查找
(4)软解析:如果存在 SQL 语句和执行计划 ,则直接执行,直接进入执行器
(5)硬解析:如果没有找到 SQL 语句和执行计划,Oracle 就需要创建解析树进行解析,生成执行计划,进入优化器
5、优化器:硬解析,如创建解析树,生成执行计划
6、执行器:拥有解析树和执行计划之后,可以在执行器中执行语句
共享池
1、包括库缓存,数据字典缓冲区等
2、库缓存区
(1)主要缓存 SQL 语句和执行计划
(2)库缓存决定 SQL 语句是否需要进行硬解析
3、数据字典缓冲区
(1)存储 Oracle 中的对象定义,比如表、视图、索引等对象
(2)当对 SQL 语句进行解析时,如果需要相关的数据,会从数据字典缓冲区中提取
4、尽量避免硬解析,提升 SQL 的执行效率
(1)在 SQL 的执行过程中,创建解析树,生成执行计划消耗大量资源
(2)在 Oracle 中,使用绑定变量,在 SQL 语句中使用变量,通过不同的变量取值来改变 SQL 的执行结果,提升软解析的可能性,但可能导致生成的执行计划不够优化,因此是否需要绑定变量还需要视情况而定
(3)使用动态 SQL 的方式,因为参数不同,会导致 SQL 的执行效率不同,同时 SQL 优化也比较困难
数据库缓冲池(Buffer Pool)
1、InnoDB 以页为单位来管理存储空间的,增删改查本质上都是在访问页面(包括读页面、写页面、创建新页面等操作)
(1)DBMS 申请占用内存来作为数据缓冲池,为了让数据表或索引中的数据随时取用,在真正访问页面之前,需要把在磁盘上的页,缓存到内存中的 Buffer Pool 之后才可以访问
(2)让磁盘活动最小化,减少与磁盘直接进行 I/O 时间
2、InnoDB 缓冲池包括:数据页、索引页、插入缓冲、锁信息、自适应索引 Hash、数据字典信息等
3、缓存原则
(1)位置 * 频次
(2)位置决定效率,在缓冲池(内存)可以直接访问数据
(3)频次决定优先级顺序,因为缓冲池的大小有限,涉及到优先级顺序,优先对使用频次高的热数据进行加载
4、缓冲池的另一个特性:预读
(1)读取数据的时候存在一个局部性原理,即使用一些数据,大概率还会使用其周围的一些数据
(2)因此采用预读机制提前加载,可以减少未来可能的磁盘 I/O 操作
5、缓冲池管理器(缓冲池如何读取数据)
(1)尽量保存经常使用的数据,在数据库进行页面读操作时,首先判断该页面是否在缓冲池中
(2)如果存在,直接读取;如果不存在,通过内存或磁盘,将页面存放到缓冲池中,再进行读取
(3)当修改数据库中的记录时,首先修改缓冲池中页里面的记录信息,然后数据库会以一定的频率刷新到磁盘上
(4)不是每次发生更新操作,都会立刻进行磁盘回写,缓冲池采用 checkpoint 机制将数据回写到磁盘上,提升数据库的整体性能
(5)当缓冲池不够用时,需要释放掉一些不常用的页,可以强行采用 checkpoint 方式,将不常用的脏页(缓冲池中被修改过的页,与磁盘上的数据页不一致)回写到磁盘上,然后再释放缓冲池中的前述脏页
6、查看缓冲池大小
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
7、设置缓冲池大小
(1)单位为 KB
(2)SQL 语句修改
SET GLOBAL innodb_buffer_pool_size = 268435456;
(3)修改配置文件
[server]
innodb_buffer_pool_size = 268435456
8、查看缓冲池的个数
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';
9、每个缓冲池实例实际占内存空间 = innodb_buffer_pool_size / innodb_buffer_pool_instances
10、更新数据流程
(1)与查询流程类似
(2)若缓冲池不存在该更新数据,则加载到缓冲池,修改内存数据,被修改的数据之后统一刷入磁盘
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战