欢迎光临
专业Linux运维二十年

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

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

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

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

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

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

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

                                1、表空间结构

                                1.1、分类

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

                                1.对于 InnoDB:

                                ibdata 文件:

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

                                .ibd 文件:

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

                                2.对于 MyISAM:

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

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

                                3. 设置

                                使用共享表空间:

                                使用独立表空间:

                                [mysqld]
                                innodb_file_per_table=1

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

                                1.2、物理结构

                                如下图所示:

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

                                主要包括以下部分:

                                1.表空间头(Header)

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

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

                                2.段(Segment)

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

                                数据段(Data Segment)

                                索引段(Index Segment)

                                回滚段(Rollback Segment)

                                3.区(Extent)

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

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

                                4.页(Page)

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

                                如下图所示:

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

                                5.空闲列表(Free List)

                                小结

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

                                如下图所示:

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

                                1.3、逻辑结构

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

                                具体如下:

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

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

                                3.事务与 MVCC 机制

                                Undo Log(回滚段中的页):

                                版本链(Version Chain)

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

                                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指定。

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

                                三种不同格式的优缺点:

                                配置如下:

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

                                2.5、binlog刷盘时机

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

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

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

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

                                3、redlog

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

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

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

                                主要体现在两个方面:

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

                                关于流程如下图所示:

                                3.1、原理及流程

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

                                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、核心作用

                                如下图所示:

                                事务持久化

                                崩溃恢复(Crash Recovery)

                                3.3、存储位置

                                3.4、特性

                                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. 事务提交流程中的协作

                                关键区别

                                2. 数据一致性保障

                                3. 崩溃恢复流程

                                3.6、应用场景

                                1. 主从复制

                                2. 数据恢复

                                3. 数据一致性

                                区别如下所示:

                                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 状态
                                SHOW VARIABLES LIKE 'expire_logs_days';
                                
                                -- 设置自动清理(单位:天)
                                SET GLOBAL expire_logs_days = 7;
                                

                                2. redolog 刷盘性能问题

                                问题innodb_flush_log_at_trx_commit=1会降低性能。

                                优化建议

                                总结

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

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

                                以上为个人经验,希望能给大家一个参考,也希望大家多多支持Linux运维。

                                脚本之家
                                赞(0) 打赏
                                未经允许不得转载:Linux老运维 » mysql表空间结构和日志的用途详解

                                觉得文章有用就打赏一下文章作者

                                非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

                                支付宝扫一扫

                                微信扫一扫