vlambda博客
学习文章列表

"三高"Mysql - Mysql的基础结构了解

引言

内容为慕课网的《高并发 高性能 高可用 MySQL 实战》视频的学习笔记内容和个人整理扩展之后的笔记,在快速视频学习一遍之后发现了许多需要补充的点,比如三次握手的连接和Mysql的内部交互流程等等,关于后续的章节也会整合多篇文章后续会陆续发布。

Mysql的连接方式

使用最多的方式是第一种方式,另外三种方式受限于特殊的平台方式实现,重点掌握第一种TCP/IP的方式即可。

  1. tcp/ip的连接形式
  2. 共享内存的连接方式
  3. 命名空间模式
  4. unix套接字的连接方式

Tcp/ip的通讯协议

这一块在视频中讲解比较浅,所以这里参考了多方资料后,以「《TCP/IP协议》」作为参考介绍三次握手和四次挥手的过程。

通讯协议也就是我们常见的三次握手和四次挥手的流程,注意这里忽略TCP/IP报文的格式介绍。

  • SYN:同步序号。
  • FIN:发送方完成标记。
  • ACK:仅当ACK=1时,确认号字段才有效,并且建立TCP连接之后所有的连接必须ACK=1。
  • ack:接受请求之后将请求序列号+1进行回送使用。
  • ISN:起始序号也别叫做Seq,该序号由时间决定,所以每一个Tcp都有一个唯一的起始序号,组成的方式是 「开始的序号、一个冒号、隐含的结尾序号」 及圆括号内的数据字节数,比如1415531521:1415531521(0),如果字节为0则被隐藏,只有当存在字节数据或者SYN、 FIN 或 RST 被设置为 1 才进行展示。
  • Mss:表示的是当前报文的最大字节数。

ISM可看作是一个32比特的计 数器,每 4ms + 1。

三次握手建立TCP连接(报问段1-3)

  • 第一步:客户端主动打开TCB端口,服务器被动打开TCB端口。发起方携带一个SYN标志,并且携带一个ISN序号Seq=x,但是需要注意的是第一步的过程这个ISN序号是隐藏传递的(因为没有传递数据),但是如果不存在数据的交换,则不会被显示。客户端发送SYN命令之后把 「SYN=1」,并且把SYN-SENT(同步-已发送状态)。
  • 第二步:服务器收到客户端TCP报文之后,也将SYN=1,并且回送一个新的ISN序号ack=x+1,并且将ACK=1表示自己收到了,然后在返回参数回送自己新的序列号表示自己的确认请求Seq=y,将状态设置为SYN-RCVD(同步收到)状态,(表示希望收到的序号为xxxx1522),最后也是指定MSS。
  • 第三步:客户端收到服务器的确认报文之后,还需要向服务端返回确认报文,确认报文的ACK=1,并且回传服务器传递的ISN序号+1(ack = y+1),以及自己的ISN序号+1(Seq = x+1),此时TCP连接进入已连接状态,ACK是可以携带数据的,但是如果不携带数据则不消耗序列号。
  • 最后一步:当服务器收到客户端的确认,也进入已连接状态。
"三高"Mysql - Mysql的基础结构了解

Mysql认证连接:

(参考资料:http://mysql.taobao.org/monthly/2018/08/07/)

Mysql的认证链接可以看作是三次交互,注意第一次请求是服务端发起的,有点类似我们去店里面买东西,首先开口的肯定是员工,比如问我们要什么东西,于是我们花钱买东西,然后把东西带走,认证过程可以类似于这样的一个过程。

  • **服务端 → 客户端 **发送初始化包:服务端首先确认是那个客户端需要连接
  • 客户端 → 服务端 验证
  • 服务端 → 认证结果消息
  • 认证通过客户端与服务端断开
"三高"Mysql - Mysql的基础结构了解

四次挥手端口tcp连接(报文段4开始)

  • 第一步(客户端):TCP发送释放连接的报文,停止发送数据,释放报文首部,把FIN=1,同时发送序列号,根据上一次传送的序列号+1传送Seq = t + 1(由于下图是在连接之后立马进行四次挥手,所以序列号没有变),此时客户端进行终止等待1的状态。注意FIN不携带数据也需要消耗序列号。
  • 第二步(服务端):服务器回送确认报文,发出确认报文,ACK=1,并且把回传序列号+1回传(ack = t + 1),然后再带上自己的序列号Seq = y,此时服务端进入CLOSE-WAIT状态(关闭等待状态),TCP服务器此时需要停止上层应用客户端向服务端请求释放,处于 **半关闭 **阶段,此时服务端依然可以向客户端发数据并且客户端需要接受并处理,关闭等待状态意味着整个状态还需要持续一段时间。
  • 第三步(客户端):客户端接收到服务端确认请求,此时客户端进入到FIN-WAIT-2终止等待2的阶段,等待服务器的释放报文。(还有一部分服务器没有发送完的数据需要处理)
  • 第四步(服务端):服务器把最后的数据处理完毕,向客户端发送释放报文,FIN=1,ack=t + 1,由于需要把剩下的数据发送完成,假设处理完成之后需要带上自己的序列号Seq=w,服务器进入 「最后确认状态」,等待客户端确认。
  • 第五步(客户端):客户端收到报文之后,发出确认 ACK=1,ack=w+1,自己的序列号为Seq = t + 1,此时客户端进入到了TIME-WAIT(时间等待状态),此时客户端还是没有释放,必须经过 「2 * MSL(最长报文寿命)」之后,客户端撤掉TCB之后才进入CLOSED状态。
  • 第六步(服务端):服务器收到客户端的请求立马进入CLOSE状态,同时撤销TCB,结束此次TCP的连接。(服务端结束TCP连接要比客户端早一些) "三高"Mysql - Mysql的基础结构了解
"三高"Mysql - Mysql的基础结构了解

为什么需要四次挥手才能关闭连接?

TCP/IP 是一种全双工的协议,任何一方关闭都需要双向的确认操作,双方关闭需要给对方发送一个FIN来终止连接,一端到FIN通知应用层的另一端终止数据的发送,而收到一个FIN仅仅说明一个方向不进行数据流动,通常关闭的一方(发送FIN的一方)为主动关闭,接受方为被动关闭,因为全双工特性双方都需要对方被动关闭。

通过下面的图可以简单了解为什么要这样设计:

"三高"Mysql - Mysql的基础结构了解

Mysql的报文格式

![image-20220318201238781](/Users/zhaoxudong/Library/Application Support/typora-user-images/image-20220318201238781.png)

Mysql的报文格式比较简单,它主要分为下面的部分,Mysql通过自己构建的协议进行内部通信,简单了解即可:

  1. 消息头:3个字节的报文长度,1个字节的序号
  2. 消息体:1个字节指令,存储数据,长度不定
  3. 指令案例:切换数据库(0x02),查询指令(ox03)

如何使用工具验证如何通信?命令是如何执行的?

连接上去之后会执行如下的操作流程。

  • 客户端→服务端:发送命令包

  • 服务端→客户端:发送回应包

命令是如何执行的?可以使用一些辅助的抓包工具查看,比如windows平台有一个wireShark的工具,我们可以通过一个简单的抓包案例查看: 在实际的开始之前我们需要弄清楚Mysql到底使用的是什么协议,MySQL客户端使用「TCP协议」作为底层传输协议,而使用Mysql公司自身的「Mysql Protocol协议」作为应用层协议作为内部通信。

这里使用window的wireShark工具抓包,读者也可以使用tcpdump进行抓包,命令行操作更加简洁:

首先是三次握手的过程:

如下面的图所示,首先由客户端发起连接请求,传送Seq序号和设置SYN为1并且设置为同步发送状态,接着服务端受到请求之后,将ACK设置为1,并且将客户端序号+1之后回送,并且也传递一个自己的序号,此时服务端也处于同步接受状态,最后当客户端受到服务端请求之后也把ack设置为1,并且传递服务端的序列号,至此建立连接。

"三高"Mysql - Mysql的基础结构了解

接下来是客户端和服务端的交互,由于这里使用了navicat进行连接测试,所以可以发现navicat在这其中发送了很多自己的包:

"三高"Mysql - Mysql的基础结构了解

这里需要注意的是在内部通信的时候Mysql使用的是自身的协议,根据客户端的命令请求返回相应的数据。

最后是四次挥手的过程,由于上面进行了详细的解释合理就不再啰嗦了,四次挥手的过程要复杂不少,客户端存在最终等待1和最终等待2的阶段,而服务端在接受到请求之后不会立刻回复客户端可以关闭,而是需要将数据传输完成之后,再回送客户端停止传送,当客户端收到断开指令之后,则会立即停止此次TCP交互,而客户端这里需要经过最长等待时间才会释放连接,所以对于服务器连接优化来说,TCP的最长等待时间是一个重要的优化点。

"三高"Mysql - Mysql的基础结构了解

数据库和excel的对比

  1. 存储和磁盘空间大小类似
  2. 数据库面向软件,提供接口
  3. excel文件级别,面向终端用户
  4. 事务:数据库千人千面

常见的架构

事件驱动架构

事件驱动的模式常见于GUI的软件当中,我们点击某个按钮的时候,会触发与之关联的其他事件组,从下面的架构图可以看到事件和事件执行之间是结偶的,有很好的复用性。

"三高"Mysql - Mysql的基础结构了解

管道-过滤器架构

管道过滤的架构比较常见是http请求过滤处理,比如我们想要对于一个请求进行不同层次的分析,对于请求次数,请求时间,或者请求来源或者对于请求拦截的处理,可以通过过滤链的方式对于请求进行处理。

"三高"Mysql - Mysql的基础结构了解

微核架构

微核架构常用于精简项目架构,通过插件的方式对于系统的核心功能增强,微核架构具有很好的灵活性,能根据不同的实际情况进行灵活组合完成不同的效果。

![image-20220318201602082](/Users/zhaoxudong/Library/Application Support/typora-user-images/image-20220318201602082.png)

分层架构

通过拆分server和存储引擎,将整个连接的步骤拆分为下面的部分,sever层负责连接管理,而存储引擎则负责与后台的交互动作。

数据库的基础架构

在Mysql的设计中,可以看到主要使用了三种架构模式:

  • 事件驱动架构
  • 分层架构
  • 微核架构

常见存储引擎介绍

  1. innodb:互联网常用,支持事务。
  2. myISAM:查询快。
  3. memory:临时内存表。
  4. Archive:归档表。

sql语句查询过程

sql的查询语句大致分为下面四个模块:

  • 查询缓存(8.0删除)
  • 分析器
  • 优化器
  • 执行器
  • 存储引擎

下面是一个SQL查询的大致步骤

  1. 查询缓存(8.0删除)

  2. 分析器

    • 分析语法,解析语句

    • 拆分编译语句

    • 解析SQL的核心步骤

  3. 优化器

    • 通过mysql的规则优化查询链路或者sql执行的过程
    • 建立并且把执行计划传递给执行器
  4. 执行器

    • 负责具体的sql执行
    • 通过存储引擎的接口进行接口调用,最后结果返回给客户端

结语

前面的章节比较基础,跳过了很多内容,本部分重点是三次握手和四次挥手的过程需要多熟悉一下,另外Mysql最值得学习的是InnoDB存储引擎,如果对于数据库设计感兴趣是肯定绕不过的。