download:2022 全面降级 Vue3 + TS 仿知乎专栏企业级我的项目完结无密含材料
一条 SQL 语句从头到尾
1. 一段 SQL 是怎么诞生的?
SQL 语句都诞生在客户端。生成一条 SQL 次要有两种形式,一种是开发人员自己手工编写,另一种是相干的 ORM 框架主动生成。一般 MySQL 运行过程中收到的 SQL 大多是 ORM 框架生成的,比如 Java 中的 MyBatis 和 Hibernate 框架。
同时,SQL 生成的时机一般与用户的请求无关。当用户在零碎中执行操作时,通常会生成一条 SQL。例如,咱们在阅读器上输出以下 URL:
此时会先请求掘金的服务器,而后掘金外部实现中的 ORM 框架会根据请求的参数生成一条 SQL,类似于上面的伪 SQL:
select * from 金爵_article 其中 userid = 862486453028888
这个 SQL 大抵意义是: 根据用户请求的“作者 ID”,查问掘金数据库文章表中该作者的所有文章信息。
从下面的案例可能显著感觉到,在用户阅读器上看到的数据一般来自于数据库,而数据库执行的 SQL 来自于用户的操作。这两者是互补的,包含任何写操作(增加、删除、更改),本质上也会转换成 SQL 的片段。让我举一个简略的例子:
请求 URL(请求 URL)
https://www.xxx.com/user/regi…
请求参数(请求参数)
{
User_name:“竹子爱熊猫”,
user _ pwd:“123456”,
用户_性别:“男”,
用户_电话:“18888888888”,
……
}
这里对用户明码的处理不够谨严,不做加密也不必在意~
复制代码
例如,在上述用户注册的情况下,当用户点击网页上的“注册”按钮时,将向目标网站的服务器发送 post 请求,而后将根据请求参数生成一条 SQL,如下所示:
insert into table_user(用户名,用户明码,用户性别,用户电话,….)
价值观 (“竹子爱熊猫”、“123456”、“男”、“188888888”,…);
复制代码
也就是说,一条 SQL 的诞生源于一个用户的请求。在开发程序时,SQL 的一般逻辑会由业务层的代码决定,而具体的 SQL 语句会根据用户的请求参数和事先定制的“SQL 骨架”做出。当然,在 Java 程序或者其余语言编写的程序中,只能生成 SQL,SQL 的真正执行需要数据库来实现。
第二,SQL 在执行之前将经历的一个过程
通过上一步,一个完整的 SQL 就诞生了。为了让 SQL 失常执行,咱们将首先获得一个数据库连接对象。上一篇对于 MySQL 架构的文章,已经讲过 MySQL 的连接层有一个叫“连接池”的小工具的保护,不过相信大家都接触过这个货色,比如 C3P0,德鲁伊,DBCP 等等在 Java 里。
至此,咱们可能在这里思考一个问题。数据库保护自己的连接池,为什么咱们还需要在 MySQL 客户端保护一个数据库连接池?接下来咱们聊聊。
2.1、数据库连接池的必要性
家喻户晓,当你要用 Java 创建数据库连接时,首先会读取配置文件中的连接地址、账号密码等信息,而后发动网络请求,根据配置的地址信息获取数据库连接对象。在这个过程中,因为涉及到网络请求,此时必然会经历 TCP 三次握手的过程。同时,在获得连接对象并实现 SQL 操作后,将开释数据库连接。这时分就需要经历 TCP 挥动四次的过程。
从下面的描述中可能清晰地感知到,Java 中创建和敞开数据库连接的过程实际上耗费了大量的成本,而且程序上线后,还需要频繁的数据库操作。所以,如果每次操作数据库都获得一个新的连接对象,那么整个 Java 程序至多有四分之一的工夫要做 TCP 三次握手 / 四次 wave 的工作,对整个零碎的后果不堪设想。….
正是因为以上原因,才出现了家喻户晓的“数据库连接池”。“数据库连接池”的思维和“线程池”是一样的,会把数据库连接到这个宝贵的资源上,用池技术来保护这个资源。也意味着当前需要进行数据库操作时,不需要自己建立连接,而是可能间接从“数据库连接池”中获取,用完之后放回连接池,达到重用的成果。
当然,连接池中保护的连接对象不会一直存在。当长时间不执行 SQL 操作时,连接池也会销毁这些连接对象,必要时再从新创建。然而什么时候创建,什么时候销毁,限度连接数等等,都是交给连接池来实现,不需要开发者自己关注。
好了~,回到后面抛出的问题,为什么需要用 MySQL 连接池在客户端保护一个连接池?
这个问题相信每个人心里都有一些答案。原因很简略。两者都使用池化技术来重用资源,俭约开销,提高性能,但针对的方向不同。
MySQL 的连接池次要是为了重用线程,因为每一个数据库连接都会被 MySQL 中的一个线程保护,而每一次连接对象调配给一个客户端,都需要经历创建线程、调配堆栈空间这样沉重的工作 … 这个过程需要工夫,资源开销也不小,所以 MySQL 通过使用池化技术来解决这些问题。
客户端的连接池次要是为了重用数据库连接,因为每一个 SQL 操作都需要经历 TCP 三次握手 / 四波的过程,同样耗时耗力,占用资源。所以也采纳了池化技术来解决这个问题。
其实也可能这样理解,MySQL 连接池保护的是工作线程,而客户端连接池保护的是网络连接。
2.2. 在执行 SQL 之前会发生什么
回到本文的主题,当生成完整的 SQL 时,咱们将首先尝试在连接池中获取一个连接对象。接下来会发生什么?
在尝试从连接池中获取连接时,如果此时连接池中有空闲的连接,可能间接获取重用。但如果不是,你首先要判断以后池中的连接数是否达到了最大数量。如果连接数已满,以后线程需要等待其余线程开释连接对象。如果没有,您可能间接创建一个新的数据库连接来使用。
假设此时连接池中没有空闲的连接,需要再次创建新的连接,那么首先会发动一个网络请求来建立连接。
①首先,将考据客户端的用户名和明码是否正确:
如果用户名不存在或明码谬误,将抛出错误代码 1045 和谬误消息。
如果用户名和明码通过考据,请转到步骤②。
②必定 MySQL 连接池中是否有空闲线程:
存在: 间接从连接池中调配一个空闲线程来保护以后客户端的连接。
否: 创建一个新的工作线程(映射内核线程,调配堆栈空间 …).
worker 线程会先查问 MySQL 自己的用户权限表,获取以后登录用户的权限信息,并进行授权。
至此,执行 SQL 前的筹备工作已经实现,执行 SQL 的通道已经打开。下一步是筹备执行 SQL 语句,工作线程将等待客户端传送 SQL。
三。SQL 语句是如何在数据库中执行的?
通过连接层的一系列工作,客户端会通过连接发送要执行的 SQL 语句,而后由 MySQL 服务层进行处理。然而根据用户的操作不同,MySQL 执行 SQL 语句时会有一些区别,SQL 语句指的是读操作和写操作。这两条 SQL 语句的执行过程是不同的。咱们先来看看 select 语句的执行过程。
3.1. 一个查问 SQL 的执行过程
在分析查问 SQL 的执行过程之前,咱们先模拟一个案例进行后续分析:
- SQL 语句
Select id fromZZ _ user
其中 user sex = 男性,user_name = 竹四号 ”;
- 表格数据
-
-
-
-
-
-
-
- +
| 用户标识 | 用户名 | 用户性别 | 用户电话 |
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
| 1 | 竹① | 男 | 1888888888 |
| 2 | 竹② | 男 | 1358888888 |
| 3 | 竹③ | 男 | 1568888888 |
| 4 | 熊猫① | 女 | 1348888888 |
| 5 | 熊猫② | 女 | 1858888888 |
| 6 | 竹④ | 男 | 17777777 |
| 7 | 熊猫③ | 女 | 166666666 |
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-