深入 MySQL (一) 体系结构

  1. MySQL 体系结构
    1. 连接器
    2. 解析器
    3. 优化器
    4. 执行器
    5. 查询缓存
    6. 存储引擎
      1. InnoDB 存储引擎
      2. MyISAM 存储引擎
      3. 其他存储引擎
    7. 参考资料

工作中常常用到 MySQL,但对 MySQL 底层原理不够熟悉。知其然,知其所以然。所以我决定深入学习 MySQL 底层知识,并产出一些备忘笔记。本文主要介绍 MySQL 的体系结构。

MySQL 体系结构

MySQL主要划分为两个部分:Server 层和存储引擎层。

Server层:实现了大部分核心功能(内置函数、存储过程、触发器、视图等等),组成模块包括连接器、查询缓存、解析器、优化器以及执行器等等;
存储引擎层:实现数据的存储和读取,向 Server 层提供操作数据的接口。支持插拔,可选的类型包括:InnoDB、MyISAM、Memory等。最常用的是 InnoDB,它从MySQL 5.5.8后成为默认存储引擎。

下图展示 MySQL 官方文档提供的体系结构图:

MySQL体系架构.png

下图展示的是简化后的 MySQL 的基本架构图。

MySQL架构图.jpg

下面展示使用 InnoDB 引擎的体系结构图以及 SQL 执行过程:

MySQL+InnoDB 体系结构图.png

连接器

连接器就像是MySQL的“门神”,它负责跟客户端建立连接、获取权限、维持和管理连接。

  • 查看连接情况

    mysql> show processlist;
    +------+------+-----------+------+---------+-------+----------+------------------+
    | Id   | User | Host      | db   | Command | Time  | State    | Info             |
    +------+------+-----------+------+---------+-------+----------+------------------+
    | 1530 | root | localhost | NULL | Sleep   | 44800 |          | NULL             |
    | 1531 | root | localhost | qds  | Query   |     0 | starting | show processlist |
    +------+------+-----------+------+---------+-------+----------+------------------+
    2 rows in set (0.03 sec)
    
  • 连接空闲超时会自动断开,可以通过 wait_timeout 参数控制,默认8小时;

  • 客户端不应频繁新建连接,尽量使用长连接;

  • 连接应该定时断开或者执行 mysql_reset_connection 重新初始化连接资源,避免占用过多内存;

  • 数据库账号权限的变更不会影响已建立的连接,只有该连接断开重连才会生效。常见的 JDBC 连接池都带有定时重连的功能,比如 HikariPool:

    private PoolEntry createPoolEntry() {
      try {
         final PoolEntry poolEntry = newPoolEntry();
         // 连接最大存活时间
         final long maxLifetime = config.getMaxLifetime();
         if (maxLifetime > 0) {
            // variance up to 2.5% of the maxlifetime
            final long variance = maxLifetime > 10_000 ? ThreadLocalRandom.current().nextLong( maxLifetime / 40 ) : 0;
            final long lifetime = maxLifetime - variance;
            // 定时任务检查连接是否空闲,空闲的连接将会被关闭
            poolEntry.setFutureEol(houseKeepingExecutorService.schedule(new Runnable() {
               @Override
               public void run() {
                  softEvictConnection(poolEntry, "(connection has passed maxLifetime)", false /* not owner */);
               }
            }, lifetime, MILLISECONDS));
         }
    
         LOGGER.debug("{} - Added connection {}", poolName, poolEntry.connection);
         return poolEntry;
      }
      catch (Exception e) {
         if (poolState == POOL_NORMAL) {
            LOGGER.debug("{} - Cannot acquire connection from data source", poolName, e);
         }
         return null;
      }
    }
    

解析器

解析器有两个功能:

  • 词法分析:将SQL语句数据库表列建立关联;
  • 语法分析:检测SQL语句是否符合MySQL语法规则。

优化器

优化器负责从不同的执行计划中选出效率最高的方案,包括决定表的连接顺序、选择哪个索引等等。此外还会涉及查询重写。

执行器

执行器主要是负责检查表权限,并且调用存储引擎的接口完成执行计划,写binlog日志等。

查询缓存

对于SELECT语句,在解析查询之前,服务器会先检查查询缓存。如果能在缓存中找到对应的查询,服务器可以直接返回缓存的结果,而不必进行解析、优化和执行等过程。

注意,频繁更新的表的查询缓存会频繁失效,不建议开启查询缓存。MySQL 8.0 版本后不再支持查询缓存。

存储引擎

MySQL 支持多种存储引擎,用户在新建表的时候可以自定义指定该表采用的存储引擎。用户也可以根据 MySQL 提供的接口定义,实现自定义的存储引擎。

最常用的第三方存储引擎是 InnoDB。在MySQL 5.5.8后,它成为默认存储引擎。

InnoDB 存储引擎

InnoDB 主要特点是:

  • 支持行锁、支持外键,并支持非锁定的读;
  • 每张表数据单独保存到一个独立的 idb 文件中;
  • 通过多版本并发控制(MVCC)来实现高并发特性,并且实现 SQL 标准的4种事务隔离级别,默认为可重复读;
  • 使用间隙锁(next-key locking)来避免幻读现象产生;
  • 每张表的主键都采用聚簇索引,如果没有显式指定主键,则默认自动生成一个6字节的 row_id 作为主键。

MyISAM 存储引擎

MyISAM 主要特点是:

  • MySQL 5.5.8 版本之前的默认存储引擎;
  • 不支持事务;
  • 不支持行锁,只支持表锁;
  • 支持全文索引;
  • 存储引擎表由 MYD 和 MYI 组成,MYD 用来存放数据文件,MYI 用来存放索引文件。

其他存储引擎

NDB 存储引擎、Memory 存储引擎、Archive 存储引擎、Federated 存储引擎、Maria 存储引擎等等。

参考资料

  • MySQL实战45讲: 非常适合入门的MySQL学习资料;
  • 《高性能MySQL》
  • 《MySQL技术内幕(InnoDB存储引擎)》

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 duval1024@gmail.com

×

喜欢就点赞,疼爱就打赏