MySQL笔记(5)-- SQL执行流程,MySQL体系结构

  • MySQL的体系结构,可以清楚地看到 SQL 语句在 MySQL 的各个功能模块中的执行过程:Server层包括连接层、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),实现所有跨存储引擎的功能比如存储过程、触发器、视图等;存储引擎层负责数据的存储和提取,MySQL5.5.5版本开始默认使用InnoDB,即你执行create table建表时,不指定引擎类型,默认使用InnoDB;

    • 连接器:

      • 连接管理(Connection Handling):当一个客户端进行连接服务端时,会得到一个server处理线程,每个连接的请求处理都是单线程的,同时服务器会缓存这些线程,所以当一个新的连接来时就不需要创建和销毁线程【MySQL5.5及其以上版本提供了一个支持线程池插件的接口】;
      • 权限认证(Authentication):当客户端连接服务端时,服务端需要对连接进行认证,即对username、host、password进行认证;
      • 安全(Securith):当客户端成功连接上服务端时,服务端会对每个连接查看它的系统权限清单【mysql> show privileges \G】,之后这个连接里面的权限判断逻辑,都将依赖于此时读到的权限,即一个用户成功建立连接后,即使对这个用户的权限做了修改,也不会影响到已经存在连接的权限,修改完后,只有再新建的连接才会使用新的权限设置;
      • 备注:
        • 连接完成后,如果没有后续的操作,这个连接就处于空闲状态,可以使用show processlist进行查看,当Command列中出现Sleep时表示该连接是空闲状态;客户端如果太长时间没有动静,连接器会自动断开连接,这个时间由参数wait_timeout控制,默认值是8小时,如果在连接被断开后,客户端再次发起请求,会收到一个错误提醒:Lost connection to MySQL server during query。这时候如果要继续,就需要重连,然后再执行请求;
        • 数据库里面的长连接成功后,如果客户端持续有请求,则一直使用同一个连接;短连接则是每次执行完很少的几次查询就断开连接,下次查询再重新建立一个;
        • 全部使用长连接后,有时候MySQL占用内存涨的很快,这是因为MySQL在执行过程中临时使用的内存是管理在连接对象中的,这些资源在断开时才会被释放,如果长连接累计下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是MySQL异常重启了;
          • 解决方案1:定期断开长连接。使用一段时间或程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连;
          • 解决方案2:MySQL版本如果是5.7及其以上,可以在每次执行一个大的操作后,通过执行mysql_reset_connection来重新初始化连接资源。这个过程不需要重连和做权限验证,会将连接恢复到刚刚创建完时的状态。
    • 分析器(Parser):MySQL分析器会创建一个内部结构(解析树),MySQL的解析行为就像单趟编译器一样,进行词法解析、语法解析、语义解析;优化器(Optimizer):当创建完解析树后,服务端会进行一系列的优化操作,包括重写查询语句、确定读表的顺序、索引选择等等,你可以使用explain进行查看细节【MySQL笔记(3)-- SQL分析】;

      • 词法解析:MySQL对语句进行识别里面的字符串分别是什么,代表什么,比如”select“是一个查询语句,吧字符串”tableName"识别为“表名 tableName",吧字符串”id“识别成”列id";
      • 语法解析:根据语法规则,判断输入的SQL语句是否满足MySQL语法,比如“elect *from tableName"这个会提示”You hava an error in your SQL syntax“的错误提醒;一般语法错误会提示第一个出现错误的位置,所以要关注的是紧接”use near"的内容;
    • 优化器(Optimizer):当解析树完成后,MySQL会进行一系列的优化操作,比如选择重写查询语句、读表顺序、索引选择等,因此优化器主要做下面的事情
      • 选择最合适的索引;
      • 选择表扫还是走索引;
      • 选择表关联顺序;
      • 优化 where 子句;
      • 排除管理中无用表;
      • 决定 order by 和 group by 是否走索引;
      • 尝试使用 inner join 替换 outer join;
      • 简化子查询,决定结果缓存;
      • 合并试图;
    • 缓冲器(Caches):缓冲器会缓存查询的结果集,当进行查询解析前,服务端会去缓存器查找,如果改查询命中缓存,那就不需要进行解析、优化、执行等等操作,直接返回缓存结果集【以key-value保存执行过的语句及查询结果】;

      • 下面是查询缓存的问题:

        • 如果对表进行了更新操作,该表的所有查询缓存都会清空;
        • 同时cache 的访问由一个单一的全局锁来控制,这时候大量的查询将被阻塞,直至锁释放。所以不要简单认为设置 cache 必定会带来性能提升。
      • MySQL官方文档显示:The query cache is deprecated as of MySQL 5.7.20, and is removed in MySQL 8.0.表示在MySQL5.7.20版本就不推荐使用,在8.0版本就移除了缓冲器;
    • 执行器:开始执行时,需要先判断你有没有这个表的执行权限,如果没有,返回没有权限的错误【同时对于命中查询缓存,会在查询缓存返回结果时做权限验证,查询会在优化器之前调用precheck验证权限】,如果有权限,打开表继续执行,执行器根据表的引擎定义,去使用这个引擎提供的接口,比如查询语句select *from table where id=1;中的id字段没有索引,那么执行器的执行流程是

      1. 调用InnoDB引擎接口取这个表的第一行,判断id是不是1,如果不是则跳过,如果是则将这行存在结果集中;

      2. 调用引擎接口取”下一行“,重复相同的判断逻辑,直到取到这个表的最后一行;

      3. 执行器将上述遍历过程中所有满足条件的行组成的结果集返回给客户端;

          完整体系结构图:    

    • 管理工具和服务(Services and utilities):提供备份(backup)、恢复(recovery)、安全(security)、复制(replication)、集群(cluster)、分区(partitioning)、工作台(workbench)功能;

    • SQL接口:接受用户的SQL命令,返回用户需要查询的结果,比如select from调用了SQL Interface;是在MySQL客户端和服务端之间进行服务的工具,SQL接口组件包括了数据处理语言【Data Manipulation Language (DML)】、数据定义语言【Data Definition Language(DDL)】,存储过程、视图、触发器等等;

    • 存储引擎:

      • MyISAM:

        • MySQL5.1及其之前版本默认的存储引擎,该存储引擎支持全文索引(基于分词创建的索引,支持复杂的查询)、压缩、空间函数等,但不支持事务和行级锁,而且崩溃后无法安全恢复;
        • 对于只读的数据或表比较小、可以忍受修复操作,则可以继续使用MyISAM;
        • MyISAM会将表存储在两个文件中:数据文件(.MYD为扩展名)和索引文件(.MYI为扩展名);
        • MyISAM支持表锁,即对整张表进行加锁,读取时会对需要读到的所有表加共享锁,写入时对表加排他锁。但是在表有读取查询的同时,也可以往表插入新的记录(并发插入,CONCURRENT INSERT);
        • 使用了MyISAM存储引擎的表,MySQL可以手工或自动执行检查(check table mytable)和修复(repair table mytable)操作,但执行表的修复可以导致一些数据丢失,并且修复操作是非常慢的;
        • 对于BLOB和TEXT等长字段,可以基于其前500个字符创建索引;
        • 创建MyISAM表的时候,如果指定了DELAY_KEY_WRITE(延迟更新索引键)选项,在每次修改执行完时,不会立刻将修改的索引数据写入磁盘,而是会写到内存的键缓冲区(in-memory key buffer)中,只有在清理键缓冲区或关闭表时才将对应的索引块写入到磁盘。这种方式大大的提升写入性能,但是在数据库或主机崩溃时会造成索引损坏,需要进行修复操作。
        • 如果表在创建并导入数据后,不会再进行修改操作,可以使用MyISAM压缩表,使用myisampack对MyISAM表进行压缩(也叫打包pack),压缩表是不能进行修改的(除非先将表解除压缩,修改数据,然后再次压缩);压缩表可以极大的减少磁盘空间占用和磁盘I/O,从而 提升了查询性能;压缩表支持索引,但索引是只读的;
      • InnoDB:

        • MySQL默认的事务型引擎,用来处理大量的短期(short-lived)事务,短期事务大部分情况是正常提交的,很少会被回滚。
        • InnoDB的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中也很流行。
        • MySQL5.1新的InnoDB plugin支持一些新特性,比如利用排序创建索引、删除或增加索引时不需要复制全表数据、新的支持压缩的存储格式、新的大型列值如BLOB的存储方式、以及文件格式管理等。
        • InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。其默认级别是repeatable read(可重复读),并且通过间隙锁(next-key-locking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁定查询设计的行,还会对索引中的间隙进行锁定,防止幻影行的插入;
        • InnoDB表是基于聚簇索引建立的,聚簇索引对主键查询有很高的性能;
        • InnoDB的存储格式是平台独立的,也就是说可以将数据和索引文件从Intel平台复制到PowerPc等其他平台;
        • InnoDB从磁盘读取数据时采用了可预测性预读,能够自动在内存中创建hash索引以加速读操作的自适应哈希索引,能够加速插入操作的插入缓冲区等;
        • InnoDB通过一些机制和工具支持真正的热备份,MySQL的其他存储引擎不支持热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可以也意味着停止读取;
      • Federated:是访问其他MySQL服务器的一个代理,它会创建一个到远程MySQL服务器的客户端连接,并将查询传输到远程服务器执行,然后提取或发送需要的数据。

      • Archive:

        • 只支持insert和select操作,在MySQL5.1之前不支持索引;
        • Archive引擎会缓存所有的写并利用zlib对插入的行进行压缩,所以比MyISAM表的磁盘I/O更少,但是每次select都需要进行全表扫描;
        • Archive表适合日志和数据采集类应用,这类应用做数据分析时往往需要全表扫描;
        • Archive引擎支持行级锁和专用的缓冲区,所以支持实现高并发的插入。在一个查询开始直到返回表中存在的所有行数之前,Archive引擎会阻止其他的select执行,以实现一致性读。另外,也实现了批量插入在完成之前对读操作也是不可见的;
      • Merge:是MyISAM引擎的一个变种,Merge表是由多个MyISAM表合并而来的虚拟表,但是将分区功能引入后,该引擎已经被放弃;

      • Memory:

        • 如果需要快速地访问数据,并且这些数据不会被修改,重启以后丢失也没关系,那么使用Memory表是非常有用的。Memory表所有的数据都保存到内存中,不需要进行磁盘I/O,表的结构在重启以后会保留,但数据会丢失;
        • 使用场景比如用于查找或映射表(将邮编和州名映射的表)、缓存周期性聚合数据的结果、保存数据分析中产生的中间数据;
        • 支持hash索引,Memory表是表级锁,并发写入的性能较低,不支持BLOB或TEXT类型的列,并且每行的长度是固定的,所以即使指定了varchar列,实际存储时也会转换成char,这可以导致部分内存的浪费;
        • 如果使用临时表来保存中间结果,该临时表使用Memory引擎,但中间结果太大超出了Memory表的限制,或者含有BLOB或TEXT字段,则临时表会转换成MyISAM表;
      • Cluster:指的是MySQL服务器、NDB集群存储引擎,以及分布式的、share-nothing的、容灾的、高可用的NDB数据库的组合被称为MySQL集群;

      • Blackhole:没有实现任何的存储机制,所有插入的数据都会丢弃,不做任何保存,但服务器会记录Blackhole表的日志,所以可以用于复制数据到备库,或只是简单地记录到日志。这种特殊的存储引擎可以在一些特殊的复制架构和日志审核时发挥作用;

      • CSV:可以将普通的CSV文件(逗号分割值的文件)作为MySQL表来处理,但不支持索引。CSV引擎可以在数据库运行时拷入或拷出文件,可以将excel等电子表格软件中的数据存储为CSV文件,然后复制到MySQL数据目录下,就能在MySQL中打开使用。同样,如果将数据写入到一个CSV引擎表,其他的外部程序也能立即从表的数据文件中读取CSV格式的数据。因此CSV引擎可以作为一种数据交换的机制;

      • Example:该引擎作为MySQL源代码中的示例,说明了如何开始编写新的存储引擎,它主要是开发人员感兴趣的。存储引擎是什么都不做的“存根”,可以使用此引擎创建表,但是不能将数据存储在表中或从表中检索数据。
  • 参考【网址需要翻墙】:

posted @ 2020-03-24 17:11  码猿手  阅读(...)  评论(...编辑  收藏