mysql表空间结构和日志的用途详解

 更新时间:2025年06月30日 09:32:37   作者:找不到、了  
这篇文章主要介绍了mysql表空间结构和日志的用途,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。

以下是mysql数据库中常用的几种日志类型:

关于每种日志的类型的功能可参考:

关于如何查询日志是否开启,可使用以下命令:

MySQL 中的binlogredolog是两种核心日志机制,它们在数据库的数据持久化主从复制崩溃恢复中扮演关键角色。

关于两者如何进行相互联系的,可参考如下:

1、表空间结构

1.1、分类

MySQL数据表以文件方式存放在磁盘中,默认使用共享表空间(0)存储。

1.对于 InnoDB:

ibdata 文件:

当使用共享表空间时,所有表的数据和索引会存储在一个共享的 ibdata 文件中。表结构以.frm文件的形式存储在与表对应的文件夹中。

.ibd 文件:

如果使用了独立表空间,InnoDB 会将每个表的结构和数据存储在独立的 .ibd 文件中。每当表的数据或索引被更新时,文件也会随之变化。表的结构仍然以.frm文件存储。

2.对于 MyISAM:

每个表的数据和索引不属于共享空间或独立空间的问题,而是直接通过三个文件来管理的:

MyISAM 数据表通常使用三种文件,分别是:

  • .frm:存储表的结构信息。
  • .MYD:存储表的数据。
  • .MYI:存储表的索引。

3. 设置

使用共享表空间:

  • 只需将innodb_file_per_table设置为0或不设置(默认值)。

使用独立表空间:

  • 可以在 MySQL 配置文件(my.cnf或my.ini)中启用独立表空间,添加如下配置:
[mysqld]
innodb_file_per_table=1

这将允许每个 InnoDB 表都有其独立的.ibd文件。

1.2、物理结构

如下图所示:

独立表空间文件(.ibd),每个独立表在磁盘上对应一个.ibd文件(test_table.ibd)

主要包括以下部分:

1.表空间头(Header)

存储表空间的基本信息,如:

  • 表空间 ID。
  • 区(Extent)的分配状态。
  • 空闲列表(Free List)、碎片列表(Fragment List)等。

用于管理表空间的物理分配和回收。

2.段(Segment)

InnoDB 的存储结构是分层的:段 → 区 → 页。每个表空间文件包含多个段,主要分为以下几类:

数据段(Data Segment)

  • 存储 B+ 树的叶子节点(数据页),即实际的行数据。
  • 对于主键索引(聚簇索引),数据段直接存储完整的行数据。

索引段(Index Segment)

  • 存储 B+ 树的非叶子节点(索引页),即索引键值和子节点指针。
  • 用于加速数据检索。

回滚段(Rollback Segment)

  • 存储事务的Undo Log(回滚数据),用于实现事务回滚和 MVCC(多版本并发控制)。
  • 每个事务可能关联一个或多个回滚段。

3.区(Extent)

每个段由多个(Extent)组成,一个区固定包含64 个连续页(默认页大小为 16KB,因此一个区大小为 1MB)。

区是 InnoDB 分配存储空间的基本单位,用于提高分配效率。

4.页(Page)

页是 InnoDB 的最小存储单元,大小默认为16KB。

如下图所示:

页的类型取决于其所属的段:

  • 数据页:存储 B+ 树叶子节点的数据(如主键索引的行数据)。
  • 索引页:存储 B+ 树非叶子节点的索引键值和子节点指针。
  • 回滚页:存储 Undo Log(回滚数据)。
  • 系统页:存储表空间的元数据(如空闲列表、区分配信息等)。

5.空闲列表(Free List)

  • 记录表空间中未被使用的页,供后续分配。
  • 当插入新数据或更新索引时,InnoDB 会从空闲列表中分配页。

小结

一张表的空间由页节点段、非页节点段、回滚段、和表空间组成。页节点段由多个区(1MB)组成,每个区由64个页(16KB)组成,每个页有多行组成。

如下图所示:

注意:此处图中的页仅代表的是叶子结点的page页。对于非叶子节点,也有相应的索引键值的页。

1.3、逻辑结构

B+ 树索引与数据组织,InnoDB 的表逻辑上通过B+ 树索引组织数据。

具体如下:

1.主键索引(聚簇索引)

  • 叶子节点:存储完整的行数据(包括所有列的值)。
  • 非叶子节点:存储主键值和指向子节点的指针。
  • 聚簇索引决定了数据在磁盘上的物理存储顺序,因此主键选择直接影响性能。

2.二级索引(辅助索引)

  • 叶子节点:存储主键值(而非完整行数据)。
  • 非叶子节点:存储索引键值和子节点指针。
  • 查询时,InnoDB 会先通过二级索引定位到主键值,再通过聚簇索引查找完整行数据。

3.事务与 MVCC 机制

Undo Log(回滚段中的页):

  • 记录事务修改前的数据版本。
  • 支持事务回滚(Rollback)和并发读取(MVCC)。

版本链(Version Chain)

  • 每个行记录通过 Undo Log 构建版本链,供不同事务读取一致性视图。

关于独立表和共享表的区别:

2、binlog

2.1. 定义

binlog(Binary Log)是 MySQL 的服务层日志,属于二进制日志,记录所有对数据库的增删改操作(不包含查询)。由 MySQL Server 层生成,与存储引擎无关(如 InnoDB、MyISAM)。默认情况下二进制日志是关闭的。

结构如下所示:

2.2. 核心作用

1.主从复制(Replication)

主库将 binlog 发送给从库,从库重放 binlog 实现数据同步。

2.数据恢复(Point-in-Time Recovery)

通过 binlog 恢复到某个时间点的数据状态。

2.3. 存储位置

默认存储在 MySQL 数据目录下的mysql-bin.xxxxxx文件中。

binlog是通过追加的方式进行写入的,可以通过max_binlog_size参数设置每个binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。

如下图所示:

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       201 |
| mysql-bin.000002 |       154 |
+------------------+-----------+
2 rows in set (0.00 sec)

2.4. 格式

MySQL 5.7.7之前,默认的格式是STATEMENTMySQL 5.7.7之后,默认值是ROW。日志格式通过binlog-format指定。

可使用以下命令,查看到:

  • Row-based:记录每一行的变更(5.7.7后默认)。
  • Statement-based:记录 SQL 语句(5.7.7之前默认)。
  • Mixed:混合模式。

三种不同格式的优缺点:

配置如下:

[mysqld]
log-bin=mysql-bin  # 开启 binlog
server-id=1        # 主库 ID

2.5、binlog刷盘时机

对于InnoDB存储引擎而言,只有在事务提交时才会记录biglog,此时记录还在内存中,那么biglog是什么时候刷到磁盘中的呢?

mysql通过sync_binlog参数控制biglog的刷盘时机,取值范围是0-N

  • 0:不去强制要求,由系统自行判断何时写入磁盘;
  • 1:每次commit的时候都要将binlog写入磁盘;
  • N:每N个事务,才会将binlog写入磁盘。

从上面可以看出,sync_binlog最安全的是设置是1,这也是MySQL 5.7.7之后版本的默认值。

设置一个大一些的值可以提升数据库性能,因此实际情况下也可以将值适当调大,牺牲一定的一致性来获取更好的性能。

3、redlog

持久性只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态

那么mysql是如何保证一致性的呢?

在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题。

主要体现在两个方面:

  • 因为Innodb是以为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了!
  • 一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!

因此使用redo log就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)。

关于流程如下图所示:

3.1、原理及流程

redo log包括两部分:一个是内存中的日志缓冲(redo log buffer),另一个是磁盘上的日志文件(redo logfile)。

  • redolog(Redo Log)InnoDB 存储引擎的事务日志,记录事务对数据页的物理修改
  • 用于保证事务的持久性(Durability),防止数据丢失。

mysql每执行一条DML语句,先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo log file。这种先写日志,再写磁盘的技术就是MySQL里经常说到的WAL(Write-Ahead Logging)技术。

在计算机操作系统中,用户空间(user space)下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间(kernel space)缓冲区(OS Buffer)。

因此,redo log buffer写入redo logfile实际上是先写入OS Buffer,然后再通过系统调用fsync()将其刷到redo log file中。

过程如下:

可以通过innodb_flush_log_at_trx_commit参数配置将redo log buffer写入redo log file的时机,

3.2、核心作用

如下图所示:

事务持久化

  • 事务提交时,先将修改写入 redolog,再异步刷盘到数据文件。

崩溃恢复(Crash Recovery)

  • 数据库重启时,通过 redolog 恢复未落盘的数据。

3.3、存储位置

  • 默认存储在ib_logfile0ib_logfile1文件中(InnoDB 专属)。

3.4、特性

  • 固定大小:默认 4GB(可通过innodb_log_file_size配置)。
  • 循环写入:当文件写满时,覆盖旧日志。
  • 物理日志:记录的是数据页的物理修改(如某个页的某个偏移量被修改)。

redo log实际上记录数据页的变更,而这种变更记录是没必要全部保存,因此redo log实现上采用了大小固定,循环写入的方式,当写到结尾时,会回到开头循环写日志。

启动innodb的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。因为redo log记录的是数据页的物理变化,因此恢复的时候速度比逻辑日志(如binlog)要快很多。

配置如下:

[mysqld]
innodb_log_file_size = 1G  # 设置 redolog 大小
innodb_flush_log_at_trx_commit = 1  # 事务提交时立即刷盘

关于redlog buffer的内存结构如下:

关于redlog buffer到redo log file持久化的流程如下图:

关于binlog和redlog的区别联系如图所示:

3.5、联系

binlog 与 redolog的联系。

1. 事务提交流程中的协作

  • 事务执行:修改数据页(内存中)。
  • 写入 redolog:事务提交时,将修改写入 redolog(确保持久性)。
  • 写入 binlog:事务提交后,将修改写入 binlog(用于主从复制和恢复)。

关键区别

  • redolog 是 InnoDB 的事务日志,确保事务的原子性和持久性。
  • binlog 是 MySQL 的逻辑日志,用于主从复制和数据恢复。

2. 数据一致性保障

  • redolog:确保事务的修改不会因宕机丢失。
  • binlog:确保主从节点的数据一致性。

3. 崩溃恢复流程

  • 恢复 redolog:数据库重启时,通过 redolog 恢复未落盘的事务。
  • 恢复 binlog:通过 binlog 恢复到某个时间点(需结合 redo log)。

3.6、应用场景

1. 主从复制

  • 主库:将 binlog 发送给从库。
  • 从库:重放 binlog 实现数据同步。

2. 数据恢复

  • 基于 binlog:恢复到某个时间点(如误删数据后回滚)。
  • 基于 redolog:恢复未落盘的事务(数据库崩溃后自动恢复)。

3. 数据一致性

  • binlog + redolog:共同保证 ACID 中的D(Durability)主从一致性

区别如下所示:

4、undolog

4.1、介绍

原子性底层就是通过undo log实现的。undo log主要记录了数据的逻辑变化,比如一条INSERT语句,对应一条DELETEundo log,对于每个UPDATE语句,对应一条相反的UPDATEundo log,这样在发生错误时,就能回滚到事务之前的数据状态。

同时,undo log也是MVCC(多版本并发控制)实现的关键。

4.2、流程

关于undolog的流程如下图所示:

4.3、日志结构

关于undolog的日志结构如下图所示:

5、常见问题与优化

1. binlog 导致磁盘空间不足

  • 问题:binlog 无限增长,占用磁盘空间。
  • 解决方案:
-- 查看 binlog 状态
SHOW VARIABLES LIKE 'expire_logs_days';

-- 设置自动清理(单位:天)
SET GLOBAL expire_logs_days = 7;

2. redolog 刷盘性能问题

问题innodb_flush_log_at_trx_commit=1会降低性能。

优化建议

  • 生产环境:保持默认值1(保证数据安全)。
  • 性能优先场景:可设置为2(每秒刷盘一次,风险略高)。

总结

MySQL中的binlog、redolog和undolog日志类型,包括它们的作用、格式和刷盘机制。binlog主要用于主从复制和数据恢复,redolog确保事务的持久性,而undolog则实现了事务的原子性。

通过理解这些日志机制,可以更好地保障数据库的安全性和性能。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • mysql sock文件存储了什么信息

    mysql sock文件存储了什么信息

    这篇文章主要为大家介绍了mysql sock文件存储了什么信息的内容详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • mysql问题之slow log中出现大量的binlog dump记录的解决方法

    mysql问题之slow log中出现大量的binlog dump记录的解决方法

    今天在查看mysql中发现比较慢,然后我使用了slow log,发现出现了大量的binlog dump记录,下面我来给大家整理一下这个问题的解决办法
    2013-09-09
  • MySQL的DML语言操作实例

    MySQL的DML语言操作实例

    在本篇文章里小编给大家整理的是一篇关于MySQL的DML语言操作实例内容,有兴趣的朋友们可以学习下。
    2020-02-02
  • 完美解决mysql客户端授权后连接失败的问题

    完美解决mysql客户端授权后连接失败的问题

    下面小编就为大家带来一篇完美解决mysql客户端授权后连接失败的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 详解grep获取MySQL错误日志信息的方法

    详解grep获取MySQL错误日志信息的方法

    在本篇文章中小编给大家整理了关于通过grep 获取MySQL错误日志信息的方法的相关知识点内容,有需要的朋友们跟着学习下。
    2018-09-09
  • MySQL缓存的查询和清除命令使用详解

    MySQL缓存的查询和清除命令使用详解

    这篇文章主要介绍了MySQL缓存的查询和清除命令使用详解,对于一些不常改变数据且有大量相同sql查询的表,查询缓存会显得比较有用一些,需要的朋友可以参考下
    2015-12-12
  • mysql5.7的安装及Navicate长久免费使用的实现过程

    mysql5.7的安装及Navicate长久免费使用的实现过程

    这篇文章主要介绍了mysql5.7的安装及Navicate长久免费使用的实现过程,本文给大家分享问题及解决方法,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • 将 Ghost 从 SQLite3 数据库迁移到 MySQL 数据库

    将 Ghost 从 SQLite3 数据库迁移到 MySQL 数据库

    如果网站流量小,直接使用 Ghost 默认的 SQLite 数据库还是很方便的,能够省去安装、配置数据库的繁琐步骤。但是,随着网站流量的增加, SQLite 就慢慢顶不住了,这时最好的选择就是使用 MySQL 数据库。
    2014-07-07
  • SQL INSERT及批量的几种方式总结

    SQL INSERT及批量的几种方式总结

    SQL提供了INSERT语句,用于将一行或多行插入表中,下面这篇文章主要给大家介绍了关于SQL INSERT及批量的几种方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • 阿里云服务器新建用户具体方法

    阿里云服务器新建用户具体方法

    本文包括了新建服务器用户和新建MySQL用户的方法,有需要的朋友可以参考一下
    2013-09-09

最新评论