MySQL的SQL执行背后隐藏了什么

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL的SQL执行背后隐藏了什么

MySQL的基本体系和架构介绍


相信在大部分的程序员在工作中都有接触过MySQL这款数据库,在MySQL的官网上边,你会看到这样的一段介绍内容:


网络异常,图片无法展示
|


大致翻译过来的意思就是说:


MySQL是世界上最受欢迎的开源数据库。无论您是快速增长的Web资产,技术ISV还是大型企业,MySQL都能经济高效地帮助您交付高性能,可扩展的数据库应用程序。


这款开源的数据库,其源码在github上边的地址为:github.com/mysql/mysql… star还是挺多的。


那么既然是一款公认好用的开源数据库,我们是否应该对它进行一个深入的了解呢?

下边我画了一个大致的MySQL基本架构图:


网络异常,图片无法展示
|


客户端


MySQL的整体结构可以分成2个大模块,分别是客户端和服务端。这里头说的客户端是指提供连接MySQL的工具集合,常见的客户端工具有mysql client,mysqladmin,mysqldump,mysqlcheck,mysqlimport,mysqlshow等等。MySQL数据库本身提供的连接方式包含有多种,其中最常见的就是基于TCP/IP协议进行连接了。基础的命令内容为:


mysql -h [地址] -u [用户名] -p [密码]
复制代码


在安装完毕了MySQL数据库之后,我们会发现数据库自身已经帮我们预先设置了一个名字叫做mysql的数据库,每次获取链接的时候就会到该库里面的User表检索账号信息以及相关的权限。


在Linux系统中,有很多进程间通信方式,套接字(Socket)就是其中的一种。但传统的套接字的用法都是基于TCP/IP协议栈的,需要指定IP地址。如果不同主机上的两个进程进行通信,当然这样做没什么问题。但是,如果只需要在一台机器上的两个不同进程间通信,还要用到IP地址就有点大材小用了。


MySQL数据库自身是支持UNIX域套接字进行通信的,因此在MySQL的文件目录下边会有这么一份文件:mysql.sock。


这份文件主要是通过Unix域套接字供我们将本地连接数据库服务器使用。


以前笔者就遇到过sock文件被修改,导致连接数据库异常的情况,例如mysql的log中出现这种报错记录:


Could not create unix socket lock file
复制代码


如果sock文件丢失的话,可以重新创建一份sock文件进行通信。


MySQL的链接分析


关于mysql的链接部分,可以先思考一下下边的这几个问题:


MySQL的链接分类包含有哪些?


其实MySQL的链接包含有很多种类型,常见的类型有:


Unix Sockets

TCP/IP

TLE/SSL


在MySQL的链接中,主要的分类有长链接类型和短连接类型。


短连接


每次客户端和服务端进行通信的时候,都需要创建链接—》进行通信—》关闭连接。这种链接的我们将其定义为短连接,从它的操作来看这种连接的行为对于资源的浪费和网络的消耗是最高的。所以通常我们在工作中较少使用。


长链接


长链接是我们工作中比较常用的类型,客户端第一次构建连接之后就不会轻易断开,这样可以给后边多次连接的程序应用所使用,这种设计的好处在于能够减少资源的损耗,相对于短连接来说要高效些。长链接通常都会被设计存储在连接池里面,从而减少连接创建的开销。如果在工作中遇到了一些并发请求比较高的业务场景,光是单单通过配置连接池的方式还是不够的,还需要有经验的开发人员在业务层进行相应的隔离。


对于一些访问量比较低的应用其实可以不使用到连接池这种较重的组件,有可能大量的长链接建立了之后都处于sleep状态,这样对于内存资源的占用会比较高。


服务端


每次客户端想要链接到服务端都需要从服务端的连接池获取相应的连接。假设我们每次连接都需要完成 构建链接,当我们获取到了链接之后,在mysql的server端可以通过这样一个命令来对每个链接的状态进行查看:


mysql> show processList;
+----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time   | State                                                  | Info             |
+----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
|  2 | system user |           | NULL | Connect | 195290 | Waiting for master to send event                       | NULL             |
|  3 | system user |           | NULL | Connect |    257 | Slave has read all relay log; waiting for more updates | NULL             |
| 19 | root        | localhost | NULL | Query   |      0 | starting                                               | show processList |
+----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
3 rows in set (0.01 sec)
复制代码


除了上边的这种情况之外,如果当连接数较多的时候,希望能够清晰查看到连接的信息可以通过下边这条指令来操作:


show status like 'Threads%';
结果内容:
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_cached    | 213   |  当前被缓存的空闲线程的数量
| Threads_connected | 191    | 正在使用(处于连接状态)的线程
| Threads_created   | 409   |  服务启动以来,创建了多少个线程
| Threads_running   | 5     |  正在忙的线程(正在查询数据,传输数据等等操作)
+-------------------+-------+
复制代码


查询缓存


对于一些数据修改变动比较少的表,MySQL内部提供了一套叫做Query Cache的缓存池来进行存储。MySQL可以通过以下命令来查看内部的查询缓存参数值:


mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| have_query_cache             | YES     |
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    |
| query_cache_size             | 1048576 |
| query_cache_type             | OFF     |
| query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+
6 rows in set (0.00 sec)
复制代码


关于查询缓存的功能,在MySQL中是根据sql语句来做缓存检索的,默认情况下该缓存属性是关闭的,对于更新频率较高的表而言,设置查询缓存其实本身的命中率并不高,因此该功能MySQL也并不提倡使用,在MySQL8.0的时候该功能也被移除了。MySQL服务器团队有一篇关于此的详细文章有所提及到移除的原因,具体地址如下:


mysqlserverteam.com/mysql-8-0-r…


语法分析器


接下来便是语法分析环节了,该模块主要是对传入的SQL语句内容做一些语法内容的校验,例如判断该语句是属于DQL还是DML等类型。其实我个人觉得MySQL里面最为复杂的部分就是SQL的语法树生产的部分,对于这部分的生成需要对编译器的原理有一定的了解,我个人的功力不是很足,所以这里借用了美团一朋友之前分享给我的图片来大概演示:


网络异常,图片无法展示
|


优化器

有时候你会发现,执行的一条SQL可能并不会按照预期的方式来走索引,这是因为MySQL内部有优化器这么一个角色的存在。当然索引的选择只是优化器的其中一项特点,优化器的目的就是通过一定的逻辑判断,将sql执行的效率发挥到最高效化。


执行器

当Sql准备好了,优化结束了,执行器便会发起sql请求引擎层的接口,这个环节中,执行器还回去判断当前请求的会话是否有权限执行相关的SQL语句。


存储引擎

可以说整个数据库的核心部分就是存储引擎环节了,不同的存储引擎对数据的存储结构和算法设计方便都有着巨大的差别,而且不同的存储引擎专门为不同的应用场景所设计。目前我们主流的存储引擎有Innodb,MyISAM,Memory,等


通过下边的这条命令我们可以看到MySQL数据库所支持的存储引擎有哪些:


mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)
复制代码


关于MySQL的整体架构介绍大概到这里就先暂时告一段落了,下一篇文章我会讲解一些关于存储引擎的比对问题。

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