MySQL的架构关键组件及执行过程

介绍MySQL的架构,每一个关键组件的作用及工作方式简单介绍

MySQL Server

Client:应用程序通常使用JDBC驱动,与MYSQL-Server交互;向MySQL服务器发送要执行的命令及SQL;

连接器:通过TCP连接池管理客户端链接、并处理认证、鉴权等操作;

查询缓存:8.0之后被移除;由于表更新则缓存失效,Server层的缓存就很鸡肋;

分析器:对SQL字符串进行词法分析、语法分析、生成AST抽象语法树;

  • 词法分析:标记SQL关键词、非关键词;
  • 语法分析:对SQL进行正确性验证,解析为语法树;

预处理器:缓存SQL模板,后续相同的SQL,使用相同的模板,只需提交参数即可;

优化器:对将执行的SQL进行分析、优化,最终生成执行计划(EXPLAIN),决定了最终的执行策略(索引选择、表的JOIN顺序等); MySQL中主要有两种优化器:

  • RBO:基于规则的优化器;
  • CBO:基于代价的优化器(主流),根据IO成本、CPU成本,优化SQL;

优化器有时会判定全表扫描比索引更快(

结果集/总数据>30
): 索引执行需要按页读取数据,全表扫描则是以块读取,并可以顺序读; 当通过索引查询的数据量比较大,可能IO的代价比全表扫描更大,优化器可能选择全表扫描; 因此创建索引,一定要有一定的区分度(选择性)才能一定程度上防止索引失效;

执行器:操作存储引擎,调用存储引擎的API,执行SQL,获取执行结果,响应客户端等;

存储引擎:真正执行SQL、存储数据的组件;不同的存储引擎使用不同的存储、读写策略;存储引擎对外暴漏Handler API,进行交互;

  • MyISAM:使用B树组织数据,只有哈希索引,不可范围查询、不支持事务;
  • InnoDB:使用B+树组织数据,支持多种索引,支持事务;

Binary Log(bin_log):记录数据的变更,有2种记录模式:

  • binlog_format = statement
    :保留完整SQL语句;
  • binlog_format = row
    :记录数据修改前后的状态;

MyISAM

使用B+树作为索引数据结构,只不过叶子节点保存数据记录的地址,而非数据记录;

  1. 支持哈希索引、全文索引;
  2. 不支持事务和行级锁定,只有表锁
  3. 读操作性能非常高效;适合读多场景;索引支持范围查询,但可以扫表来范围查询;

InnoDB存储引擎

Buffer Pool

  • 大小由:
    innodb_buffer_pool_size
    决定;
  • 个数由:可以有多个,提升并发性能;由
    innodb_buffer_pool_instances
    决定,各实例间隔离;
  • 内存操作单元为:对应InnoDB页(16KB + 页描述信息)
  • LRU缓存:双向链表缓存热点数据;
    • 使用LRU算法(近期最少使用)进行内存管理;当内存不足时,淘汰不常使用的页,将其刷入磁盘;
    • 缓存命中率:由于LRU机制,尽量不要查询不需要的列,挤占内存,导致LRU缓存命中率降低;
  • Free链:即空闲缓存页,InnoDB需要从磁盘加载新的页时,会从Free链中取空白页,装载数据;
  • Flush链:脏页链,存放被修改的脏页,放入链表尾部,由后台线程顺序刷入磁盘中;刷入完成后,将空页加入Free链;

Redo Log:InnoDB使用redo_log的顺序磁盘IO来加速持久化;

  • InnoDB的数据最终存储在磁盘,如果直接写入磁盘,就会以随机IO的方式写入;
  • 因此Innodb的数据写入
    BufferPool
    中时,就算是写入成功了;
  • 但是宕机会丢失,因此使用
    redolog
    来以顺序IO的方式最快的进行持久化;保证宕机仍能够从
    redolog
    中恢复数据; Undo Log:用于事务回滚和MVCC数据版本;会定期清理不再需要的版本数据;(永远不需要读到的版本)

MySQL实例和库

一个MySQL实例可以包含多个逻辑库;

  • 库与库之间的表、试图、存储过程、事务都相互隔离;
  • 多个库共享MySQL实例的配置、CPU、内存资源、连接池、InnoDB缓存池、磁盘IO、物理存储;
  • 多个库之间的锁资源是隔离的(如表锁),不会存在表锁竞争;

单节点多库的限制:

  1. 单节点多库:并不会提高并发度,多个库共享连接池、内存资源并不会提高并发度;
  2. 多库共享InnoDB缓存池;如果某个库有热点查询,其他库的缓存可能被清除;

什么场景需要单节点多库:

  • 租户的数据隔离;
  • 单表数据量过大的分库分表,提升SQL执行效率;
  • 环境的隔离:开发环境、测试环境;