MySQL总体架构简述
MySQL总体架构简述
(一)简介
为什么我们需要先学习MySQL的基础架构先呢?原因很简单,当我们需要了解一件事物的时候,我们只有站在宏观的层面,才能层层剥丝抽茧的去理解问题。我们学习MySQL的时候应该先从高纬度理解问题,最后看到里面有哪些组件,一层层的拆解,这样让我们对MySQL有更深入的理解。,我们先看MySQL总体的逻辑架构图,如下所示:
观察图发现,MySQL主要可以分为两个部分:Server层、存储引擎层。我们下面先大概看一下这两层的主要功能。
从图中不难看出,不同的存储引擎共用一个Server层。可以看到Server层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖了MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如触发器、视图等。
我们需要注意,存储引擎层负责数据的存储和提取,其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎。现在最常用的存储引擎是InnoDB,它从MySQL 5.5.5版本开始成为了默认存储引擎。这也说明了create table建表的时候,如果不指定引擎类型,默认使用的就是InnoDB。当然也可以指定存储引擎,例如create table语句中使用engine=memory,来指定使用内存引擎创建表。
下面我们从Server层开始仔细研究两层层中的各个模块:
(二)Server层
1. 连接器
MySQL的连接器是MySQL的server层的第一个模块。当我们用客户端来连接MySQL服务器的时候,处理这个连接请求的就是连接器模块。
MySQL客户端和服务器端的连接使用的是TCP协议,在完成TCP握手之后,连接器开始进行身份认证。如果用户名或密码不对,那么连接器会抛出一个 "Access denied for user"的错误,客户端结束执行。如果用户名密码认证通过,那么连接器会到权限表中查出账号拥有的权限,以后所有的权限判断都是基于此时查出的权限。这意味着,一个用户成功建立连接后,即使root用户修改了这个用户的权限,对之前的连接也不能生效,只有修改之后生成的连接才能获取到新的权限。
连接建立成功后,可以进行很多次SQL操作,如果长时间没有操作,连接器会自动断开连接。断开连接的时间是由wait_timeout控制的,默认值是8小时。如果连接被断开后,客户端再次发生请求,会收到“Lost connection to MySQL server during query”的错误提示。这时候想要执行查询,就需要重连了。
刚刚讲的连接为长连接,与之对应的连接就称为短连接。短连接的概念为:进行连接后,发送一次请求后就断开连接,下一次数据库请求必须重新进行连接。短连接会频繁创建连接,如果在繁忙系统中可能会导致系统端口数被耗尽,从而无法连接。但是,长连接虽然避免了频繁的创建连接,但是连接过程中请求使用到的内存空间需要到连接关闭才释放。所以如果长连接时间过长,可能会导致数据库内存猛增。
2. 查询缓存
查询缓存和我们在其他地方见到的缓存的作用基本一致,主要作用就是将热点数据放入内存中,若查询语句命中缓存则可以直接取出而不必再去表中查找。
在解析一个查询语句之前,如果查询缓存是打开的,那么MySQL会优先检查这个查询是否命中查询缓存中的数据。如果当前的查询恰好命中了查询缓存,那么在返回查询结果之前MySQL会检查一次用户权限。若权限没有问题,MySQL会跳过所有其他阶段(解析、优化、执行等),直接从缓存中拿到结果并返回给客户端。这种情况下,查询不会被解析,不用生成执行计划,不会被执行。
很显然,查询缓存一旦命中,对于性能的提升看似是十分巨大的,但为什么大多数教材都建议不要打开查询缓存呢?首先,我们要明白cache的访问由一个单一的全局锁来控制,这时候大量的查询将被阻塞,直至锁释放,因此效率是十分低下的。另外,对于某些写频繁的系统,开启查询缓存功能可能并不能让系统性能有提升,有时反而会有下降。原因是MySql为了保证查询缓存的内容和实际数据绝对一致,当某个数据表发生了更新、删除及插入操作,MySql都会强制使所有引用到该表的查询SQL的查询失效。对于密集写操作,启用查询缓存后很可能造成频繁的缓存失效,间接引发内存激增及CPU飙升,对数据库系统这是一种极大的负担。
因此,这个弊大于利的查询缓存功能已经在MySQL8.0版本中被整个移除。
3. 分析器
在执行SQL语句之前,MySQL需要对SQL语句做解析,分析器先进行词法分析 ,MySQL需要识别出你这条sql语句字符串里面的字符串分别是什么,代表什么意思。
接着就是进行语法分析了,根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个SQL语句是否满足MySQL语法。如果你的语法错误,就会报错。
这里分析器所做的工作和其他语言的编译器很类似,就是通过SQL语句来识别客户端的要求,从而分析出要对数据库执行什么样的操作。
4. 优化器
经过了分析器后,在执行之前,还需要经过优化器的处理,为什么还需优化器呢?答案就是需要将数据库操作的过程进行优化,提高执行速度。
MySQL优化器使用基于成本的优化方式(Cost-based Optimization),以SQL语句作为输入,利用内置的成本模型和数据字典信息以及存储引擎的统计信息决定使用哪些步骤实现查询语句,也就是查询计划。
查询优化和地图导航的概念非常相似,我们通常只需要输入想要的结果(目的地),优化器负责找到最有效的实现方式(最佳路线)。需要注意的是,导航并不一定总是返回最快的路线,因为系统获得的交通数据并不可能是绝对准确的。与此类似,优化器也是基于特定模型、各种配置和统计信息进行选择,因此也不可能总是获得最佳执行方式。
优化器内部非常复杂,在这里我们点到为止即可,下面列出优化器的一些功能:
- 选择最合适的索引
- 选择表关联顺序
- 优化where子句
- 排除管理中无用表
- 决定order by和group by是否走索引
- 尝试使用inner join替换outer join
- 简化子查询,决定结果缓存
- 合并视图
5. 执行器
经过优化器知道了查询计划,于是就进入了执行器阶段,开始执行语句。开始执行的时候,要先判断一下对这个表有没有执行查询的权限,如果没有,就会返回没有权限的错误。如果有权限,就继续往下执行,这时候执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
获取结果之后,执行器会将结果集返回给客户端,一次查询结束。
(三)存储引擎层
提到存储引擎,用的最多的三个就是InnoDB、MyISAM和Memory。我们来对比着简单了解一下这三种存储引擎。
1. InnoDB
InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,同时InnoDB是MySQL默认的存储引擎。InnoDB主要有以下特性:
使用 InnoDB存储引擎,MySQL将在数据目录下创建一个名为ibdata1的10MB大小的自动扩展数据文件,以及两个名为ib_logfile0和ib_logfile1的5MB大小的日志文件。
2. MyISAM
MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物。MyISAM主要有以下特性:
使用MyISAM引擎创建数据库,将产生3个文件。文件的名字以表名字开始,扩展名为文件类型:frm文件存储表定义、数据文件的扩展名为.MYD(MYData)、索引文件的扩展名时.MYI(MYIndex)。
3. MEMORY
MEMORY存储引擎将表中的数据存储到内存中,为查询和引用其他表数据提供快速访问。MEMORY主要有以下特性:
就这三种存储引擎而言,我们可以看一下如何在实际业务场景中选择:
InnoDB: 支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为它支持事务的提交(commit)和回滚(rollback)。
MyISAM: 插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低,也可以使用。
MEMORY: 所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMORY。它对表的大小有限制,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。
2020年9月6日