MySQL介绍
MySQL基本架构
下面是MySQL的基本架构图。
sql语句首先经过连接器,与MySQL建立连接,再经过分析器,判断sql语句是否合法。之后再到缓存中查看是否有这条语句的缓存(MySQL8.0已经删除),若没有则经过优化器,对如何进行查询进行优化,之后再经过执行器,调用存储引擎来获得我们想要的数据。
由于缓存已经在8.0版本被移除,MySQL内部主要有连接器、分析器。优化器、执行器、存储引擎5个部分。
连接器
连接器负责跟客户端建立连接、获取权限、维持和管理连接。
建立连接之后,如果客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。
数据库连接有长连接和短连接,和http中的长短连接很相似。
长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。
由于建立连接的过程十分复杂,所以建议建立长连接,并使用一个连接池来维护建立的长连接。
使用长连接会有一些弊端。
MySQL 在执行过程中临时使用的内存是管理在连接对象里面的,这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大。
有两个解决策略
1.定期断开长连接。
2.定期初始化长连接资源(MySQL5.0以后才支持)
分析器
分析器的任务是对语句进行词法分析和语法分析。
词法分析和编译器中的词法分析器有些类似,它将MySQL的关键字和变量找出来并进行分类,为后续的语法分析做准备。
语法分析根据语法规则判断当前的SQL语法是否合法。
优化器
经过分析器可以确定我们语句的任务,那么如何完成这个任务是有很多种方案的。到底使用哪种方案去完成这个任务由优化器敲定。
优化器的目标是在所有可以完成任务的方案中找到最优的方案。它的具体工作为
在表有多个索引时,确定使用哪个索引。
在有多表关联时,决定表的连接顺序。
执行器
敲定方案之后,执行器的任务就是真正执行我们要做的任务了。
在实际情况中,有些表是不能被访问的,比如有个表正在被写,此时我们就无法读这个表了。
所以,执行器的第一个工作就是查看我们的连接对表有没有执行权限,权限通过之后,就打开表,调用存储引擎给我们提供的接口,去读取数据。
存储引擎
存储引擎就是存储数据的地方了。
对于MySQL服务层的执行器而言,存储引擎为其提供接口
对于数据而言,存储引擎将之以一种有序的方式组织好,方便用户的查询。
同时,如果存储引擎也支持事务处理,保证事务操作的原子性。
存储引擎innoDB
存储引擎的架构图如下。
可以看出,存储引擎分为3个部分,工作线程,内存池,文件。
我们先对存储引擎进行需求分解
1.首先,存储引擎需要组织好我们的数据文件
2.其次,存储需要能够对外提供接口,所以它也应该能够处理执行器传来的IO请求。
3.存储引擎需要一些内存来组织一些结构来支持事务原子性的实现,查询结果的保留等
4.存储引擎应该能够定时清理一些不再需要的内存
根据这些需求分解,我们可以更加好理解存储引擎的架构。
现在介绍一下存储引擎的三个部分
工作线程
工作线程主要有四种。
Master Thread
这是最核心的一个线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括赃页的刷新、合并插入缓冲、UNDO 页的回收等.
IO Thread
在 InnoDB 存储引擎中大量使用了异步 IO 来处理写 IO 请求, IO Thread 的工作主要是负责这些 IO 请求的回调处理。
Purge Thread
事务被提交之后, undo log 可能不再需要,因此需要 Purge Thread 来回收已经使用并分配的 undo页. InnoDB 支持多个 Purge Thread, 这样做可以加快 undo 页的回收。
Page Cleaner Thread
Page Cleaner Thread 是在InnoDB 1.2.x版本新引入的,其作用是将之前版本中脏页的刷新操作都放入单独的线程中来完成,这样减轻了 Master Thread 的工作及对于用户查询线程的阻塞。
内存池
innoDB的内存中的数据结构主要分为4个部分:
1、缓冲池(Buffer Pool);
缓冲池是一块用于缓存被访问过的表和索引数据的内存区域,缓冲池允许在内存中处理一些被用户频繁访问的数据,在某一些专用的服务器上,甚至有可能使用80%的物理内存作为缓冲池。
缓冲池的存在主要是为了通过降低磁盘IO的次数来提升数据的访问性能。
2、写缓冲(Change Buffer);
写缓冲是为了缓存缓冲池(Buffer Pool)中不存在的二级索引(Secondary Index)页的变更操作的一种特殊的内存数据结构。
这些变更通常是一些Insert、Update、Delete等DML操作引发的,如果有一些其它的读操作将这些被变更的二级索引页加进了缓冲池(Buffer Pool),则这些变更会被马上合并至缓冲池中以保证用户可以读取到一致的数据。
3、日志缓冲(Log Buffer);
InnoDB将数据的每次写优化为了批量写,这便以降低磁盘IO的次数,为了防止一些数据尚未写入硬盘就断电了,需要记录日志。
而日志缓冲就是用来缓存一些即将要被写入磁盘日志文件(log files)中的数据。
4、自适应哈希索引(Adaptive Hash Index);
在InnoDB中,用户是不可以直接去创建哈希索引的,这个自适应哈希索引是InnoDB为了加速查询性能,会根据实际需要来决定是否对于一些频繁需要被访问的索引页构建哈希索引,它会利用key的前缀来构建哈希索引。这样做可以提高查询性能,因为索引采用类似B+树的结构进行存储,B+树的单key查询时间复杂度为O(log2n),但是优化为哈希索引后,单key的查询时间复杂度就为O(1)了。
文件
MySQL文件为存储在磁盘上的结构。
首先是日志文件,记录了MySQL数据库的各种类型活动。
日志文件包括错误日志,二进制日志,慢查询日志,查询日志。
套接字文件。套接字文件用于支持使用unix域套接字方式连接本地MySQL。
Pid文件。记录MySQL使用的进程PID。
表结构定义文件。记录数据表的结构定义
存储引擎文件。
存储引擎文件包括表空间文件和重做日志文件。
表空间逻辑的存放innoDB中的所有数据。表空间由段,区,页组成。数据单位由行,页,区,段依次增大。
重做日志记录innoDB存储引擎的事务日志,能在实例失败时保证数据的完整性。
如所在主机由于掉电导致实例失败,可以使用重做日志恢复到掉电前的时刻,保证数据的完整性。