二、MySQL底层存储原理与结构

1 前言

本章目标:

  • 了解构成MySQL数据库和InnoDB存储引擎的各种类型的文件。
  • 理解InnoDB存储引擎的内存结构和磁盘结构。

2 文件

MySQL数据库和InnoDB存储引擎的文件有参数文件、日志文件、socket文件、pid文件、表结构文件、存储引擎文件。下面将会对这些文件逐一介绍。

参数文件

告诉MySQL实例启动时在哪里可以找到数据库文件,并且指定某些初始化参数,这些参数定义了某种内存结构的大小等设置,还会介绍各种参数的类型。
可以使用show variables查看数据库中的所有参数,也可以通过LIKE来过滤参数名,如 show variables like ‘innodb_buffer%’;
MySQL参数文件中的参数可以分为两类:动态参数和静态参数。动态参数可以在MySQL实例运行中进行更改,静态参数在整个实例生命周期内都不能进行更改。

日志文件

日志文件是用来记录MySQL实例对某种条件做出相应执行时写入的文件。MySQL中有六种日志文件,分别是:错误日志(error log)、常规查询日志(general log)、二进制日志(bin log)、慢查询日志(slow query log)、重做日志(redo log)、回滚日志(undo log)、中继日志(relay log)。

  • 错误日志(error log)
    错误日志记录MySQL的启动、运行、关闭过程信息。该日志不但记录了出错信息,也记录了警告或正确的信息,通过分析错误日志可以快速定位故障进行排错。可使用show variables like 'log_error’查看当前的错误日志配置。
    请前往【MySQL官网-错误日志】,了解更多详细信息。

  • 常规查询日志(general log)
    当客户端连接或断开连接时,服务器将信息写入此日志,并记录从客户端接收的每个 SQL语句。建议关闭这种日志(默认是关闭的)。
    请前往【MySQL官网-常规查询日志】,了解更多详细信息。

  • 二进制日志(bin log)
    包含二进制文件“事件”描述数据库更改,如表创建操作或对表数据的更改。它还包含可能已进行更改的语句的事件(例如删除),除非使用基于行的日志记录。二进制日志还包含有关每个语句占用更新数据的时间的信息。二进制日志有两个重要用途:
    a. 对于复制,复制源服务器上的二进制日志提供要发送到副本的数据更改的记录。 源将其二进制日志中包含的事件发送到其副本,副本执行这些事件以进行与源服务器上相同的数据更改。
    b. 某些数据恢复操作需要使用二进制日志。恢复备份后,将重新执行备份后记录的 二进制日志中的事件。这些事件使数据库从备份点开始保持最新状态。
    请前往【MySQL官网-二进制日志】,了解更多详细信息。

  • 慢查询日志(slow query log)
    待补充,敬请期待…

  • 重做日志(redo log)
    待补充,敬请期待…

  • 回滚日志(undo log)
    待补充,敬请期待…

  • 中继日志(relay log)
    待补充,敬请期待…

socket文件

当用UNIX域套接字方式进行连接时需要的文件。

pid文件

MySQL实例的进程ID文件。

表结构文件

用来存放MySQL表结构定义文件。

存储引擎文件

因为MySQL表存储引擎的关系,每个存储引擎都会有自己的文件来保存各种数据。这些存储引擎真正存储了记录和索引等数据。

3. InnoDB 体系结构

在这里插入图片描述
上图展示了InnoDB 存储引擎的内存结构和磁盘结构。

4 内存结构

InnoDB内存数据对象如下图:
在这里插入图片描述
InnoDB 提供了自己的内存组件,主要包括缓冲池(Buffer Pool)、变更缓冲(Change Buffer)、日志缓冲(Log Buffer)以及自适应哈希索引(Adaptive Hash Index)技术。

缓冲池

缓冲池是 InnoDB 在内存中的一个缓冲区域,主要用于缓存访问过的表和索引等数据。缓冲池利用内存直接处理数据,避免磁盘操作,从而加快了数据处理的速度。
使用show variables like ‘innodb_buffer_pool%’;命令可查看InnoDB 缓冲池相关的配置:

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool%';
+-------------------------------------+----------------+
| Variable_name                       | Value          |
+-------------------------------------+----------------+
| innodb_buffer_pool_chunk_size       | 8388608        |
| innodb_buffer_pool_dump_at_shutdown | ON             |
| innodb_buffer_pool_dump_now         | OFF            |
| innodb_buffer_pool_dump_pct         | 25             |
| innodb_buffer_pool_filename         | ib_buffer_pool |
| innodb_buffer_pool_in_core_file     | ON             |
| innodb_buffer_pool_instances        | 1              |
| innodb_buffer_pool_load_abort       | OFF            |
| innodb_buffer_pool_load_at_startup  | ON             |
| innodb_buffer_pool_load_now         | OFF            |
| innodb_buffer_pool_size             | 8388608        |
+-------------------------------------+----------------+
11 rows in set (0.00 sec)

缓冲池管理算法

缓冲池通过LRU(Latest Recent Used,最近最少使用)算法进行管理。最频繁使用的页在LRU列表的前端,而最少使用的页在LRU列表的尾端。当缓冲池不能存放新读取的页的时候,将首先释放LRU列表中尾端的页。

变更缓冲

待补充,敬请期待…

日志缓冲

待补充,敬请期待…

自适应哈希索引

待补充,敬请期待…

5. 磁盘结构

InnoDB逻辑存储结构

InnoDB存储引擎所有数据都被逻辑地存放在一个表空间。表空间由段(segment)、区(extent)、页(page)组成。如下图所示:

在这里插入图片描述

  • 表空间:在默认情况下,InnoDB存储引擎所有数据都存放于一个表空间。可通过“innodb_file_per_table”参数可以使每张表内的数据单独存放到一个表空间,需要注意的是,这些独立的表空间存放的只是数据、索引和插入缓冲,而Undo信息、事务信息、双写缓冲等还是存放在共享表空间。
  • 段:常见的有数据段、索引段、回滚段等。InnoDB存储引擎表是索引组织的,数据即索引,索引即数据。那么数据段即为B+树的叶子节点(leaf node segment),索引段即为B+树的非叶子节点(non-leaf node segment)。
  • 区:由64个连续的页组成的,每个页大小为16KB,即每个区的大小为1MB。对于大的数据段,InnoDB存储引擎最多每次可以申请4个区,以此来保证数据的顺序性能。在启用了参数innodb_file_per_talbe后,创建的表默认大小是96KB,这里不是默认不是1M的原因是:在每个段开始时,先有32个页大小的碎片页(fragment page)来存放数据,当这些页使用完之后才是64个连续页的申请。
  • 页:页是InnoDB磁盘管理的最小单位。InnoDB页默认大小16KB(操作系统页式管理中的页大小为4KB,InnoDB存储引擎申请连续的4页)。常见的页类型有:数据页、Undo页、系统页、事务数据页、插入缓冲位图页、插入缓冲空闲列表页、未压缩的二进制大对象页、压缩的二进制大对象页。
  • 行:InnoDB存储引擎是面向行的(row-oriented),每个页最多允许存放(16KB/2-200)行的记录,即7992行记录。

InnoDB数据页结构

待补充,敬请期待…

InnoDB行记录格式

InnoDB存储引擎提供了Compact 和 Redundant 两种格式来存放行记录数据,这也是目前使用最多的一种格式。Redundant 格式是为了兼容之前版本而保留的,MySQL 5.1之后的版本默认为 Compact 行格式。可以使用命令SHOW TABLE STATUS LIKE 'table_name’来查看当前表使用的行格式。

Compact 行记录格式如下:
在这里插入图片描述

  • 首部是一个非 NULL 变长字段长度列表,并且是按照列的顺序逆序放置的,长度为:若列的长度小于255字节,则用1字节表示;若大于255个字节,用2字节表示。变长字段的长度不可以超过两个字节,因为 VARCHAR 类型的最大长度限制为 65535。
  • 变长字段之后的第二个部分是 NULL 标志位,该位指示了该位数据中是否有 NULL 值,有则用1表示。
  • 接下来的部分是记录头信息(record header),固定占用5字节(40位)。
  • 最后的部分就是实际存储每个列的数据。需要特别注意的是,NULL 不占用该部分任何空间,即 NULL 除了占用 NULL 标志位之外,实际存储不占用空间。另外,每行数据除了用户定义的之外,还有两个隐藏列,事务ID列和回归指针列,分别是6和7字节大小。如果 InnoDB 表没有定义主键,还会增加一个6字节的 rowid 列。

双写缓冲

待补充,敬请期待…

上一篇:一、MySQL体系结构
下一篇:三、MySQL索引与算法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值