1、MySQL逻辑体系架构

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_缓存

可见mysql的组成部分有以下内容:

  • 连接池组件
  • 管理服务和工具组件
  • SQL接口组件
  • 查询分析器组件
  • 优化器组件
  • 缓冲(Cache)组件
  • 插件式存储引擎
  • 物理文件
    mysql的存储是基于表的,而不是数据库。
    mysql的特点就是他是插件式的表存储引擎

1.1、连接层

1.1.1、概述

是一些客户端和连接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于tcp/ip的通信。

【基本功能】
  • 完成一些类似于连接处理、授权认证、及相关的安全方案。
  • 引入了线程池的概念,为通过认证安全接入的客户端提供线程。
  • 实现基于SSL的安全链接。
  • 服务器也会为安全接入的每个客户端验证它所具有的操作权限。
【MYSQL的线程管理】

当MySQL启动(MySQL服务器就是一个进程),等待客户端连接,每一个客户端连接请求,服务器都会新建一个线程处理(如果是线程池的话,则是分配一个空的线程),每个线程独立,拥有各自的内存处理空间,但是,如果这个请求只是查询,没关系,但是若是修改数据,很显然,当两个线程修改同一块内存是会引发数据同步问题的。

1.1.2、通信方式

【常见的通信机制】

全双工:能同时发送和接收数据,例如平时打电话。
半双工:指的某一时刻,要么发送数据,要么接收数据,不能同时。例如早期对讲机
单工:只能发送数据或只能接收数据。例如单行道

【mysql的通信方式】

MySQL客户端/服务端通信协议是“半双工”的:

  • 在任一时刻,要么是服务器向客户端发送数据,要么是客户端向服务器发送数据,这两个动作不能同时发生。
  • 一旦一端开始发送消息,另一端要接收完整个消息才能响应它,所以我们无法也无须将一个消息切成小块独立发送,也没有办法进行流量控制。
【传送过程】

客户端——>服务器

  • 客户端用一个单独的数据包将查询请求发送给服务器,所以当查询语句很长的时候,需要设置max_allowed_packet参数。但是需要注意的是,如果查询实在是太大,服务端会拒绝接收更多数据并抛出异常。

服务器——>客户端

  • 服务器响应给用户的数据通常会很多,由多个数据包组成。
  • 但是当服务器响应客户端请求时,客户端必须完整的接收整个返回结果,而不能简单的只取前面几条结果,然后让服务器停止发送。

开发建议

  • 在实际开发中,尽量保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯
  • 这也是查询中尽量避免使用SELECT *以及加上LIMIT限制的原因之一。

2.1.3、权限验证

mysql中存在4个控制权限的表,分别为user表,db表,tables_priv表,columns_priv表

【mysql权限表的验证过程为】

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_存储引擎_02

【mysql的权限分级】

全局性的管理权限: 作用于整个MySQL实例级别
数据库级别的权限: 作用于某个指定的数据库上或者所有的数据库上
数据库对象级别的权限:作用于指定的数据库对象上(表、视图等)或者所有的数据库对象上

【四个权限表的内容】

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_缓存_03

2.1.4、查询连接状态

【查询方式】

对于一个MySQL连接,或者说一个线程,任何时刻都有一个状态,该状态表示了MySQL当前正在做什么。有很多种方式能查看当前的状态,最简单的就是下面这个

SHOW FULL PROCESSLIST

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_存储引擎_04

command列就是状态

【几种连接状态的含义】

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_客户端_05

连接出现问题:对于出现问题的连接通过kill {id}的方式杀掉

2.1.4、连接类型

  • 长连接:长连接是相对于短连接来说的。长连接指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。
  • 短连接:是指通讯双方有数据交互时,就建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。
【长连接的问题】

使用长连接后,随着连接数不断增加,会导致内存占用升高,因为 MySQL 在操作过程中会占用内存来管理连接对象,只有等到连接断开后才会释放。
如果连接一直堆积,就会导致内存占用过大,被系统强行杀掉,也就是会出现 MySQL 重启。

【解决方案】

1、定期断开长链接,每隔一段时间或者执行一个占用内存的大查询后断开连接,依次释放内存

2、MySQL 5.7+ 的版本中提供了 mysql_reset_connection 来重新初始化连接资源,这时不需要重新连接,就可以将连接恢复到刚刚创建完时的状态

2.2、服务层

2.2.1、概述

主要完成大多数的核心服务功能。

  • sql接口,并完成缓存的查询。
  • 所有跨存储引擎的功能也在这一层实现,如过程,函数等。
  • 在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定查询表的顺序,是否利用索引等。最后生成相应的执行操作。如select语句,服务器还会查询内部的缓存。如果缓存空间足够大,这样就解决大量读操作的环境中能够很好的提升系统的性能。

2.2.2、SQL Interface-SQL接口

SQL接口,接收用户的sql命令,并且返回用户需要查询的结果。比如select from就是调用SQL Interface。

2.2.3、Cache&Buffer查询缓存

mysql8.0版本后被删除
mysql的缓存主要的作用是为了提升查询的效率

【存储形式】
  1. 缓存以key和value的哈希表形式存储,key是具体的sql语句,value是结果的集合。
  2. 将缓存存放在一个引用表中,通过一个哈希值引用,这个哈希值包括了以下因素,即查询本身、当前要查询的数据库、客户端协议的版本等一些其他可能影响返回结果的信息。
  3. 如果查询可以在缓存中找到key,那么该key对应的value会直接返回给客户端,如果没有命中则需要执行后续解析、优化和执行阶段的操作,执行后也会缓存起来。(任何字符上的不同,例如空格、注解等都会导致缓存的不命中。)
【为什么被删除】
  1. 针对表进行写入或更新数据时,将对应表的所有缓存都设置失效。
  2. 对于更新压力大的数据库来说,查询缓存的命中率会非常低。除非你的业务就是有一张静态表,很长时间才会更新一次。
  3. 在查询之前必须先检查是否命中缓存,浪费计算资源。
  4. 如果这个查询可以被缓存,那么执行完成后,MySQL 发现查询缓存中没有这个查询,则会将结果存入查询缓存,这会带来额外的系统消耗。
  5. 如果查询缓存很大或者碎片很多时,这个操作可能带来很大的系统消耗。
【不会被缓存的情况】
  1. 包含函数NOW()和CURRENT_DATE()的查询
  2. 包含任何用户自定义函数,存储函数,用户便令,临时表
  3. mysql数据库中的系统表或者包含任何列权限的表
  4. 对于 InnoDB 引擎来说,当一个语句在事务中修改了某个表,那么在这个事务提交之前,所有与这个表相关的查询都无法被缓存。因此长时间执行事务,会大大降低缓存命中率
  5. 当查询语句中设置了 SQL_NO_CACHE,则不会被缓存
  6. 当查询的结果大于 query_cache_limit 设置的值时,结果不会被缓存
【查询缓存执行状态】
show status like 'Qcache%'

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_客户端_06


MYSQL逻辑读 物理读 mysql数据库的逻辑结构_客户端_07

【缓存执行状态】

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_MYSQL逻辑读 物理读_08

【手动控制是否查询缓存】

mysql是提供了按需使用缓存的设置,将参数query_cache_type设置成DEMAND,这样对于默认的SQL语句都不使用查询缓存。

用SQL_CACHE显式指定,像下面这个语句一样

mysql> select SQL_CACHE * from T where ID=10;

2.2.4、Parser-解析器、分析器

SQL命令传递到解析器的时候会被解析器验证和解析。

  1. 将SQL语句进行语义和语法的分析,分解成数据结构,然后按照不同的操作类型进行分类,然后做出针对性的转发到后续步骤,以后SQL语句的传递和处理就是基于这个结构的。
  2. 如果在分解构成中遇到错误,那么就说明这个sql语句是不合理的
【分析器的执行过程】

在分析器中就通过语义规则器将select from where这些关键词提取和匹配出来,MySQL会自动判断关键词和非关键词,将用户的匹配字段和自定义语句识别出来。这个阶段也会做一些校验:比如校验当前数据库是否存在user表,同时假如User表中不存在userId这个字段同样会报错:unknown column in field list.

2.2.5、Optomizer查询优化器

【概述】

SQL语句在查询之前会使用查询优化器对查询进行优化。

就是优化客户端请求的 query(sql语句) ,根据客户端请求的 query 语句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出一个最优的策略,告诉后面的程序如何取得这个 query 语句的结果。

比如表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。

【功能】

进行sql语句的优化,根据执行计划(explain)进行最优的选择,匹配合适的索引选择最佳的执行方案

2.3、引擎层

存储引擎真正的负责MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信,不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需进行选取。

mysql区别于其他数据库的最重要的特点就是插件式表存储引擎。mysql插件式的存储引擎架构提供标准的管理和服务支持

存储引擎基于表而不是基于数据库

2.4、存储层

主要是将数据存储在运行于裸设备的文件系统之上,并完成于存储引擎的交互。

2、Mysql的存储引擎

2.1、InnoDB存储引擎

从mysql数据库5.5.8版本开始,innoDB存储引擎是默认的存储引擎

  • 支持事务
  • 特点是行锁设计、支持外键
  • innoDB把所有的数据都放在一个逻辑的表空间的中,这个表空间就想黑盒子一样由InnoDB自身进行管理。
  • InnoDB通过多版本控制(MVCC)来获取高并发性,并且实现了SQL标准的4中隔离级别。
  • InnoDB提供了缓冲(insert buffer)、二次写(double write)、自适应哈希索引(adaptive hash index)、预读(read ahead)等高性能和高可用的功能。
  • 数据存储采用聚集方式,如果不指定主机,会给表生成一个6字节的ROWID,作为主键

2.2、MylSAM存储索引

是mysql5.5.8版本之前的默认存储引擎

  • 不支持事务、表锁设计
  • 支持全文索引
  • 缓冲只缓存索引文件,不缓冲数据文件
  • MyISAM存储引擎是由MYD和MYI组成的,MYD存放数据文件,MYI存储索引文件。

2.3、NDB存储引擎

NDB是一个集群存储引擎,特点是所有的数据都放在内存中,所以主键查找速度极快。

2.4、Memory存储引擎

Memory存储引擎(之前称为HEAP存引擎)把表的数据放在内存中,如果发生数据库重启或在崩溃,表中的数据将会小时。适合用于存储临时数据的临时表,以及数据仓库中的纬度表。

只支持表锁,并发性能差,并且不支持TEXT和BLOLB类类型。

2.5、Federated引擎

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_客户端_09

2.6、索引产生的文件

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_MYSQL逻辑读 物理读_10

MYSQL逻辑读 物理读 mysql数据库的逻辑结构_存储引擎_11