【MYSQL】MySQL整体结构

无论你是前端还是后端,只要是一个合格的开发者,对于MySQL这个名词相信都不陌生,MySQL逐渐成为了最受欢迎的关系型数据库,无论你是大前端,亦或是Java、Go、Python、C/C++、PHP....等这些语言的程序员,对于MySQL是必然要掌握的核心技术之一,程序员不能没有MySQL,就像西方不能失去耶路撒冷一般。

当然,MySQL也不仅仅是唯一的数据库,与它类似的关系型数据库竞品还有很多,例如Oracle、SQLServer、PostgreSQL、DB2....,这其中使用最为广泛的是Oracle,但Oracle实际上并不怎么受程序员欢迎,或者说Oracle并不怎么受中小企业的Boss欢迎,原因嘛大家都清楚,无非因为它收费罢了。

也正是由于Oracle收费的原因,才导致MySQL像如今这么流行,正所谓时势造英雄,MySQL作为免费的开源数据库,也正是抓住了这个风口,所以才越发流行。对于MySQL,用一句话形容很贴切:"天不生我MySQL,编程万古如长夜"。

一、MySQL概述与系列预告

MySQL数据库是由瑞典的MySQL AB公司开发的,后面这家企业被Sun公司收购,最后Sun公司又被Oracle74亿美元收购,所以本质上MySQL现在隶属于Oracle旗下,因此大家也会发现,MySQL后面的高版本会有收费版出现。

实际上如果MySQL没有并入Oracle的话,是有很大几率问鼎数据库榜首的,造化弄人。

整个MySQL系列会按上述目录进行全面阐述,但上述目录只是预期规划内容,实际撰写过程中可能会适当调整,但给出的技术点都会事无巨细的讲到,内容只多不少,因此大家感兴趣的话,可以点个关注,由我伴随诸君一同彻底掌握MySQL数据库。

二、MySQL整体结构浅析

本章作为MySQL系列的开篇之作,当然也有一定的原因,毕竟只有先对MySQL的整体架构有了一个宏观的认知,才能更好的理解每个细节点的知识。

MySQL与我们开发项目时相同,为了能够合理的规划整体架构设计,也会将整个MySQL服务抽象成几个大的模块,然后在内部进行实现,因此先来看看MySQL的整体架构,开局先上一张图:

从上往下看,依次会分为网络连接层、系统服务层、存储引擎层、以及文件系统层,往往编写SQL后,都会遵守着MySQL的这个架构往下走。

  • 连接层:主要是指数据库连接池,会负责处理所有客户端接入的工作。
  • 服务层:主要包含SQL接口、解析器、优化器以及缓存缓冲区四块区域。
  • 存储引擎层:这里是指MySQL支持的各大存储引擎,如InnoDB、MyISAM等。
  • 文件系统层:涵盖了所有的日志,以及数据、索引文件,位于系统硬盘上。

OK~,除了上述的四层外,还有客户端,这个客户端可以是各类编程语言,如Java、Go、Python、C/C++、PHP、Node、.Net....,也可以是一些数据库的可视化软件,例如Navicat、SQLyog等,也可以是mysql-cli命令行工具。总之,只要能与MySQL建立网络连接,都可以被称为是MySQL的客户端。

MySQL-Server就是上述图中的那玩意儿,一般来说,客户端负责编写SQL,而服务端则负责SQL的执行与数据的存储。

MySQL的整体架构有了简单了解后,接下来详细的拆解一下MySQL-Server的每个层面。

三、网络连接层

在之前的《网络之旅》的文章中,我们提到过一点:当一个客户端尝试与MySQL建立连接时,MySQL内部都会派发一条线程负责处理该客户端接下来的所有工作。而数据库的连接层负责的就是所有客户端的接入工作,MySQL的连接一般都是基于TCP/IP协议建立网络连接,因此凡是可以支持TCP/IP的语言,几乎都能与MySQL建立连接。

其实MySQL还支持另一种连接方式,就是Unix系统下的Socket直连,但这种方式一般使用的较少。

虽然MySQL是基于TCP/IP协议栈实现的连接建立工作,但并非使用HTTP协议建立连接的,一般建立连接的具体协议,都会根据不同的客户端实现,如jdbc、odbc...这类的。在这里先暂且不纠结连接MySQL时的协议类型,先来看看一般是怎么连接MySQL的?如下:

mysql -h 127.0.0.1 -uroot -p123456

例如上述这条指令,-h表示MySQL所在的服务器IP地址,-u表示本次连接所使用的用户名,-p则代表着当前用户的账号密码,当执行这条指令后,会与MySQL-Server建立网络连接,也就是会经历《TCP的三次握手过程》。当然,MySQL也支持SSL加密连接,如果采用这种方式建立连接,那还会经过《SSL多次握手过程》,当握手结束,网络建立成功后,则会开始正式的数据库连接建立工作。

TCP网络连接建立成功后,MySQL服务端与客户端之间会建立一个session会话,紧接着会对登录的用户名和密码进行效验,MySQL首先会查询自身的用户表信息,判断输入的用户名是否存在,如果存在则会判断输入的密码是否正确,如若密码错误或用户名不存在就会返回1045的错误码,如下信息:

ERROR 1045 (28000): Access denied for user 'zhuzi'@'localhost' (using password: YES)

如果你在连接数据库的过程中,出现了上述的错误信息,那绝对是你输入的用户名或密码错误导致的,当账号及密码正确时,此时就会进入MySQL的命令行,接下来可以执行SQL操作。

但实际上,在用户名和密码都正确的情况下,MySQL还会做一些些小动作,也就是会进行授权操作,查询每个用户所拥有的权限,并对其授权,后续SQL执行时,都会先判断是否具备执行相应SQL语句的权限,然后再执行。

OK~,经过上述流程后数据库连接就建立成功了,数据库连接建立成功后,MySQL与客户端之间会采用半双工的通讯机制工作,与之对应的还有"全双工、单工"的工作模式:

  • 全双工:代表通讯的双方在同一时间内,即可以发送数据,也可以接收数据。
  • 半双工:代表同一时刻内,单方要么只能发送数据,要么只能接受数据。
  • 单工:当前连接只能发送数据或只能接收数据,也就是"单向类型的通道"。

到这里,MySQL也会"安排"一条线程维护当前客户端的连接,这条线程也会时刻标识着当前连接在干什么工作,可以通过show processlist;命令查询所有正在运行的线程:

执行结果如下(root账号可以查询所有线程):

  • Id:当前线程的ID值,可以利用这个ID,使用kill强杀线程。
  • User:当前线程维护的数据库连接,与之对应的用户是谁。
  • Host:与当前线程保持连接关系的客户端地址(IP+Port)。
  • db:目前线程在哪个数据库中执行SQL
  • Command:当前线程正在执行的SQL类型,如:
    • Create DB:正在执行创建数据库的操作。
    • Drop DB:正在执行删除数据库的操作。
    • Execute:正在执行预编译的SQLPreparedStatement)。
    • Close Stmt:正在关闭一个PreparedStatement
    • Query:正在执行普通的SQL语句。
    • Sleep:正在等待客户端发送SQL语句。
    • Quit:当前客户端正在退出连接。
    • Shutdown:正在关闭MySQL服务端。
  • Time:表示当前线程处于目前状态的时间,单位是秒。
  • State:表示当前线程的状态,有如下几种:
    • Updating:当前正在执行update语句,匹配数据做修改操作。
    • Sleeping:正在等待客户端发送新的SQL语句。
    • Starting:目前正在处理客户端的请求。
    • Checking table:目前正在表中查询数据。
    • Locked:当前线程被阻塞,其他线程获取了执行需要的锁资源。
    • Sending Data:目前执行完成了Select语句,正在将结果返回给客户端。
  • Info:一般记录当前线程正在执行的SQL,默认显示前一百个字符,查看完整的SQL可以使用show full processlist;命令。

其实从这个结果上来看,我们能够很明显的看到数据库中各个线程的信息,这条指令对于以后做线上排查时有很大的作用,目前先简单了解,接着来看看数据库连接池。

3.1、数据库连接池(Connection Pool)

Connection Pool翻译过来的意思就是连接池,那为什么需要有这个东西呢?因为前面聊到过,所有的客户端连接都需要一条线程去维护,而线程资源无论在哪里都属于宝贵资源,因此不可能无限量创建,所以这里的连接池就相当于Tomcat中的线程池,主要是为了复用线程、管理线程以及限制最大连接数的。

连接池的最大线程数可以通过参数max-connections来控制,如果到来的客户端连接超出该值时,新到来的连接都会被拒绝,关于最大连接数的一些命令主要有两条:

  • show variables like '%max_connections%';:查询目前DB的最大连接数。
  • set GLOBAL max_connections = 200;:修改数据库的最大连接数为指定值。

对于不同的机器配置,可以适当的调整连接池的最大连接数大小,以此可以在一定程度上提升数据库的性能。除了可以查询最大连接数外,MySQL本身还会对客户端的连接数进行统计,对于这点可以通过命令show status like "Threads%";查询:

其中各个字段的释义如下:

  • Threads_cached:目前空闲的数据库连接数。
  • Threads_connected:当前数据库存活的数据库连接数。
  • Threads_createdMySQL-Server运行至今,累计创建的连接数。
  • Threads_running:目前正在执行的数据库连接数。

对于几个字段很容易理解,额外要说明的一点是Threads_cached这个字段,从名称上来看,似乎跟缓存有关系,其实也没错,因为这里是有一个数据库内部的优化机制。当一个客户端连接断开后,对于数据库连接却不会立马销毁,而是会先放入到一个缓存连接池当中。这样就能在下次新连接到来时,省去了创建线程、分配栈空间等一系列动作,但这个值不会是无限大的,一般都在32左右。

连接池的优化思想与Java线程池相同,会将数据库创建出的连接对象放入到一个池中,一旦出现新的访问请求会复用这些连接,一方面提升了性能,第二方面还节省了一定程度上的资源开销。

相关推荐
全栈师7 分钟前
SQL Server中关于个性化需求批量删除表的做法
数据库·oracle
Data 31715 分钟前
Hive数仓操作(十七)
大数据·数据库·数据仓库·hive·hadoop
BergerLee44 分钟前
对不经常变动的数据集合添加Redis缓存
数据库·redis·缓存
程序员大金1 小时前
基于SpringBoot+Vue+MySQL的装修公司管理系统
vue.js·spring boot·mysql
gorgor在码农1 小时前
Mysql 索引底层数据结构和算法
数据结构·数据库·mysql
-seventy-1 小时前
SQL语句 (MySQL)
sql·mysql
bug菌¹2 小时前
滚雪球学Oracle[6.2讲]:Data Guard与灾难恢复
数据库·oracle·data·灾难恢复·guard
一般路过糸.2 小时前
MySQL数据库——索引
数据库·mysql
Cengineering2 小时前
sqlalchemy 加速数据库操作
数据库
Cikiss2 小时前
微服务实战——平台属性
java·数据库·后端·微服务