MySQL | SQL 语句是怎样执行的呢?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 高产似母猪,废话少说,今天刚好读到一篇关于 MySQL 语句底层如何执行的文章,以下是我的理解,分享给你们。

简单的 SQL 语句


mysql> select * from User where ID=10086;


上面是一条非常简单的 SQL 查询语句,咋一看是不是觉得很简单,但却不懂它内部的执行流程?


根据自己的理解,我画了个不那么专业的执行流程图,先给出这条 SQL 语句的执行流程,再逐步解析每个流程,执行流程图如下:


640.jpg


你可以清晰地看到,MySQL 其实分为两层,server 层和存储引擎层。


server 层包括 连接器、查询缓存、分析器、优化器、执行器等,这一层涵盖了 MySQL 的大部分核心功能,包括你平时用到的很多函数。从图中可以看出,不同的引擎使用同一个 Server 层。


存储引擎层则是复制数据的存储和读取。由于在 MySQL 中,存储引擎是以插件形式存在的。所以它支持 InnDB、MySAM、Memory 等引擎,其中用得最多的就是 InnDB。


连接器


这条语句执行的第一步就是连接数据库,这时会调用连接器干这个事情。他负责跟客户端建立连接、获取权限、维持和管理连接。


连接命令一般是这么写的,相信不用我过多解释。


mysql -h 192.168.0.201 -P 3306 -u root -p123


输入这条命令之后最底层就是客户端与数据库之间进行经典的 TCP 握手通信,连接完成后,连接器就开始校验当前用户的身份。


  • 如果账号密码不对,就会抛出 Access denied for user 的异常。
  • 如果账号密码正确,连接器就会读取当前用户此时所拥有的的权限,值得注意的是,在连接过程中,即使你用管理员账号修改当前用户的权限,丝毫不会影响它在本次连接的权限,你的修改需要等到下次连接才会生效。
  • 如果你长时间没有操作数据库,这个连接自动断开,这个时间默认是 8 小时。这个时候你要操作数据库就必须重连。


如何取舍长连接和短连接?


长连接指的是数据库持续拥有一个连接,短连接指每次执行完很少的几次操作就断开连接。


但是有个问题,长连接临时使用的内存管理在连接对象中,如果使用长连接,内存占用太大导致 MySQL 重启,而连接本来就是一个非常复杂的操作(想想 TCP 通信),我们又不能使用短连接。那如何取舍呢?


可以考虑以下方案:


  1. 定期断开长连接,使用一段时间,或者程序里面判断占用内存较大时,断开连接。
  2. MySQL 5.7 以上版本,可以在执行一个大的操作后,运行 mysql_reset_connection 来初始化链接资源,这个过程并不需要重连,但还是会恢复到初始连接的状态。


查询缓存


若开启了查询缓存,之前执行过的语句会以 key-value 对的形式存在。典型应用就是 redis。


连接建立完成后,接下来,select 语句就是到查询缓存中判断是否有当前语句的缓存,若有直接返回结果集。


使用了查询缓存效率会很高。但一般不建议用,为什么?


为什么不建议用查询缓存?


查询缓存失效的频率非常高,只要有对表的更新,这个表的所有查询缓存就失效了,你辛苦存起来的缓存,还没使用就这么一下子就没了。对于经常更新的数据库来说,查询缓存根本没必要存在。除非你的表数据是不常变动的,建议你使用查询缓存。


分析器


如果没命中缓存就要开始执行语句了,但在执行之前 MySQL 需要知道你想干嘛。因此会对语句进行分析,这时就是分析器的活了。


首先 MySQL 会做词法分析,以上述语句为例,MySQL 就会识别出 select 关键字,分析这是查询语句,再把 User 识别成 表名 User,把字符串 "ID" 识别出 "列ID"。


优化器


经过分析器知道了做什么,在开始执行前还需要经过优化器。


它的作用就是在表里面有多个索引的时候。决定使用那个索引;或者在一个语句有多表关联的时候,决定各个表的连接顺序。优化器会选择效率最高的优化方案。


执行器


翻过万水千山终于来到了执行器,在开始执行之前,执行器会判断当前用户对表 User 是否有查询的权限。如果没有就报权限异常,(那如果当前用户没有权限,但命中了查询缓存,那 MySQL 会在返回结果时做权限认证)


如果有权限,执行流程如下(以上述语句为例):


  1. 调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10086,如果不是则跳过,如果是则将这行存在结果集中。
  2. 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
  3. 执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户。


至此执行结果完成。


后语


以上就是我对 MySQL 查询语句执行流程的理解,希望对你们有帮助。最后,对 Python 、Java 感兴趣请长按二维码关注一波,我会努力带给你们价值,如果觉得本文对你哪怕有一丁点帮助,请帮忙点好看,让更多人知道。如有问题或建议,请后台留言,我会尽力解决你的问题。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7天前
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
99 11
|
27天前
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
1月前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
1月前
|
SQL 关系型数据库 MySQL
MySQL 高级(进阶) SQL 语句
MySQL 提供了丰富的高级 SQL 语句功能,能够处理复杂的数据查询和管理需求。通过掌握窗口函数、子查询、联合查询、复杂连接操作和事务处理等高级技术,能够大幅提升数据库操作的效率和灵活性。在实际应用中,合理使用这些高级功能,可以更高效地管理和查询数据,满足多样化的业务需求。
188 3
|
1月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
1天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
10 0
|
28天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
56 3
|
28天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
66 3
|
28天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
86 2
|
1月前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
263 15