• 深入理解MySQL binlog

深入理解MySQL binlog

2025-05-06 01:00:05 栏目:宝塔面板 36 阅读

binlog 是 MySQL 最为重要的日志文件,MySQL 数据的备份恢复、主从复制都依赖 binlog,相比于其他日志文件,binlog 可以说是刚需了。

binlog 常见命令

为了对 binlog 有一个直观的认知,我们先来看几个命令。

首先,默认情况下 binlog 并不会开启,我们可以通过下面的 show variabkes like‘log_bin’命令查看 binlog 的开启状态:

MySQL> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | OFF   |
+---------------+-------+

如果你需要开启 binlog,可以在 my.ini 配置文件中可以加入下面的配置来开启:

log_bin=/home/MySQL/bin-log.log

开启 binlog 以后,我们就可以看看 binlog 的内容了。由于 binlog 本身是二进制文件,我们不能直接打开查看,但我们只关心 binlog 内容的意义而不是内容本身,因此我们可以用 MySQL 提供的如下命令来查看 binlog 内容:

show binlog events;

在 MySQL 中,输入上述命令后,我们能看到如下所示的返回结果:

MySQL> show binlog events;
+----------------+------+-------------+-----------+-------------+---------------
| Log_name       | Pos  | Event_type  | Server_id | End_log_pos | Info
+----------------+------+-------------+-----------+-------------+---------------
| bin-log.000001 |    4 | Format_desc |         1 |         107 | Server ver: 5.7.29-log, Binlog ver: 4                         |
| bin-log.000001 |  99 | Query       |         1 |         175 | BEGIN
                                                |
| bin-log.000001 |  166 | Intvar      |         1 |         203 | INSERT_ID=9
                                                |
| bin-log.000001 |  200 | Query       |         1 |         315 |insert into user (age,name) values(1,"test") |
| bin-log.000001 |  331 | Xid         |         1 |         342 | COMMIT /* xid=22 */                                           |
+----------------+------+-------------+-----------+-------------+---------------

在这个返回的结果中,最重要的是 Event_type 和 Info 这两个字段,其余字段不影响我们学习理解 binlog,就不赘述了。其中,Info 是命令的具体内容,可以看到 Info 里面是具体执行的 SQL 语句。而 Event_type 是事件类型,它的作用是记录我们对 MySQL 所有变更操作的类型。

目前 MySQL 有 30 多种事件类型,归类了你对 MySQL 的所有变更操作。这些操作日志的内容共同组成了我们的 binlog,其中 Event_type 是 binlog 日志中的一个字段,因此认识 Event_type 对理解 binlog 的内容非常重要,我们后面会挑选几个 Event_type 类型介绍。

通过上面的返回的结果,我们可以看到,每个指令、每个动作都是一行记录,而在 binlog 里每一行被称作一个事件。也就是说 binlog 是由一个又一个事件组成的。

binlog 文件格式

在讲解 binlog 事件之前,我们先看看 binlog 的文件格式分类。binlog 有 3 种格式类型,分别是 STATEMENT、ROW、MIXED:

  • STATEMENT

STATEMENT 是 binlog 的默认格式,我们后面对 binlog 的分析也是基于 STATEMENT 格式进行的。这个格式下,每一条修改数据的 sql 都会被记录到 binlog 中,slave 端再根据 sql 语句重现。

但 STATEMENT 的缺点也很明显,比如你用了 uuid 或者 now 这些函数,你在主库上执行的结果并不是你在从库执行的结果,这种随时在变的函数会导致复制的数据不一致。

  • ROW

在 ROW 模式下,我们只需要知道行数据最终被修改成什么样了,不会出现 STATEMENT 下动态函数的问题。但 ROW 的缺点是每行数据的变化结果都会被记录,比如执行批量 update 语句,更新多少行数据就会产生多少条记录,使 binlog 文件过大,而在 STATEMENT 格式下只会记录一个 update 语句而已。

  • MIXED

MIXED 包含了 STATEMENT 和 ROW 模式,它会根据不同的情况自动使用 ROW 模式和 STATEMENT 模式,MIXED 除了包含 STATEMENT 和 ROW 特性之外,还有一些针对自身优化的特性,比如压缩方式和一些特殊标记等等。

binlog 事件

在前面我们说了,binlog 由若干个事件组成,其中开头的第一个事件叫 Format_description,中文翻译为格式描述事件,文件结尾的最后一个事件叫做 rotate,中文翻译为日志轮换事件。其中 Format_description 包含了 binlog 的服务器信息、文件状态的关键信息等。

如果 MySQL 服务关闭或者重启,那么 MySQL 进程会自动创建一个新的 binlog,同时写入一个新的 Format_description。简单来说 Format_description 就是一个文件头。rotate 则包含下一个 binlog 的文件信息,它由 MySQL 写完 binlog 后添加到 binlog 的末尾,注意 rotate 只有当 binlog 写完才会有,binlog 没有写完的情况下是没有 rotate 的。

binlog 的基础结构如下,中间黄色部分就是我们执行的每一个事件。除了 select,剩下所有操作基本都会被记录,binlog 不记录 select 是因为 select 不会产生变更。

图片

binlog 对所有产生变化的操作做了分类,我们挑几类常见的介绍一下:

  • QUERY

这是最常见的类型,执行更新语句时会生成此事件,包括:create,insert,update,delete 等等。比如我们手动执行一个插入语句,然后再使用上面提到的 show binlog events 看一下下面的 binlog 文件内容:

insert into test values(1,'yafeng');
| bin-log.000001 | 412 | Query       |         1 |         536 | insert into test values(1,'yafeng');                                                      |
| bin-log.000001 | 520 | Xid         |         1 |         563 | COMMIT /* xid=30 */

和前面的日志内容相比,我们可以看到,经过 insert 操作,binlog 文件中多了一个 Query 类型的记录。

  • XID

事务提交时产生的事件,上面 insert 语句就是一个事务,因此除了 QUERY 记录还产生了一条 XID 记录。

  • FORMAT_DESCRIPTION

我们在前面提到了 FORMAT_DESCRIPTION,它是 binlog 的文件头记录。

  • ROTATE

当 binlog 写完后会另启一个新 binlog 来记录日志,旧的 binlog 文件末尾会追加这个事件,什么情况下 binlog 会写完呢?有 3 种情况,一个是手动执行 flush logs 命令,第二是重启 MySQL,第三是 binlog 文件大于 max_binlog_size 参数配置的大小。

  • INTVAR

SQL 中使用了 AUTO_INCREMENT 的字段,就会产生这个事件。

  • STOP

当 MySQL 停止时会生成此事件,是的,你没听错,连 MySQL 的停止也会被记录到 binlog。

  • RAND

SQL 中包含随机数函数的语句将产生 RAND 事件。

以上几个事件是 STATEMENT 格式下常见的几个,还有一些事件工作在 ROW 和 MIXED 格式下。binlog 在记录每个事件的时候也使用了 header 和 body 的格式,即 header 存储元数据,body 存储具体执行的语句。当然这并不是很重要,因为计算机领域中从网络协议到虚拟机到操作系统几乎都采用了类似的设计。下面我们来介绍 binlog 的变种文件 relay log。

relay log

relay log 中文名是中继日志,在主从复制的时候会辅助 binlog 完成复制任务。relay log 有着和 binlog 类似的格式和结构,可以看作是 binlog 的亲兄弟。唯一不同的地方是 relay log 多了 master.info 和 relay-log.info 两个文件。

master.info 和 relay-log.info 的文件内容非常小,一般以 info 为后缀结尾的文件都不大,里面记录了文件的指针。其中 master.info 记录 I/O 线程读取 binlog 的实时位置指针,relay-log.info 记录了 SQL 线程读取 relay log 的实时文件指针。 I/O 线程和 SQL 线程可以看作是在从库上工作的两个流水线工人,I/O 线程负责原材料的运输,写入本地的 relay log 中,SQL 线程负责从 relay log 获取原材料并加工。

现在我们再来回顾一下主从复制的流程,实际上这个流程有很多隐藏细节,既然我们今天提到了 master.info 和 relay-log.info,我们就来深入讲一下这个流程:

  1. 首先主库收到客户端请求语句,在语句结束之前向 binlog 写入事件。
  2. 之后,从库连接到主库,主库的 dump 线程从 binlog 读取日志并发送到从库的 IO 线程。
  3. I/O 线程从 master.info 读取到上一次写入的最后的位置。
  4. I/O 线程写入日志到 relay log,更新 master.info 的最后位置。
  5. SQL 线程从 relay-log.info 读取进上一次读取的位置,然后在数据库中执行 sql,执行完更新 relay-log.info 的最后位置。

总结

今天我们聊了 MySQL 的 binlog,binlog 是 MySQL 最重要的日志文件。同时,由于 binlog 本身是二进制的,所以它的结构很神秘。好在 MySQL 为我们提供了一些命令去查看它的内容。

通过今天的学习,我们也知道了 binlog 有 STATEMENT、ROW 和 MIXED 3 种模式,不同的格式下会有不同的事件,他们各有优缺点,MySQL 默认使用 STATEMENT 模式。

每个 binlog 文件都是由不同的事件组成的,几乎所有变更操作都是事件。MySQL 有 30 多种事件,其中我们介绍了 QUERY、XID、FORMAT_DESCRIPTION 等几个事件。binlog 有个孪生兄弟 relay log,这是从库从主库克隆过来的 binlog,它只是用在主从复制场景。relay log 有两个 info 文件 master.info 和 relay-log.info,其中 master.info 服务于从库的 I/O 线程,relay-log.info 服务于从库的 SQL 线程。结合这两个 info 文件,我们回顾了主从复制的完成过程,加深了印象。

本文地址:https://www.yitenyun.com/179.html

搜索文章

Tags

数据库 API FastAPI Calcite 电商系统 MySQL 数据同步 ACK 双主架构 循环复制 Web 应用 异步数据库 生命周期 序列 核心机制 Deepseek 宝塔面板 Linux宝塔 Docker JumpServer JumpServer安装 堡垒机安装 Linux安装JumpServer esxi esxi6 root密码不对 无法登录 web无法登录 Windows Windows server net3.5 .NET 安装出错 宝塔面板打不开 宝塔面板无法访问 SSL 堡垒机 跳板机 HTTPS Windows宝塔 Mysql重置密码 无法访问宝塔面板 HTTPS加密 查看硬件 Linux查看硬件 Linux查看CPU Linux查看内存 ES 协同 修改DNS Centos7如何修改DNS scp Linux的scp怎么用 scp上传 scp下载 scp命令 防火墙 服务器 黑客 Serverless 无服务器 语言 存储 Oracle 处理机制 Spring SQL 动态查询 Linux 安全 网络架构 工具 网络配置 MySQL 9.3 开源 PostgreSQL 存储引擎 加密 场景 RocketMQ 长轮询 配置 HexHub Canal 架构 InnoDB 缓存方案 缓存架构 缓存穿透 Rsync 日志文件 MIXED 3 信息化 智能运维 响应模型 线上 库存 预扣 聚簇 非聚簇 索引 B+Tree ID 字段 数据 业务 AI 助手 数据库锁 监控 单点故障 优化 万能公式 云原生 GreatSQL Hash 字段 分库 分表 DBMS 管理系统 SpringAI Redis 自定义序列化 Redis 8.0 openHalo OB 单机版 SVM Embedding PostGIS 系统 SQLark 虚拟服务器 虚拟机 内存 数据集成工具 SQLite Redka ​Redis 机器学习 推荐模型 sqlmock sftp 服务器 参数 分页查询 Netstat Linux 服务器 端口 排行榜 排序 自动重启 运维 缓存 聚簇索引 非聚簇索引 共享锁 • 索引 • 数据库 RDB AOF 技术 Testcloud 云端自动化 查询 EasyExcel MySQL8 prometheus Alert SQLite-Web 数据库管理工具 同城 双活 Postgres OTel Iceberg 分布式架构 分布式锁​ 数据类型 OAuth2 Token Entity 开发 StarRocks 数据仓库 Doris SeaTunnel 向量数据库 大模型 不宕机 IT 数据备份 容器化 MongoDB 容器 IT运维 人工智能 推荐系统 分页 数据结构 连接控制 机制 AIOPS 部署 LRU Milvus 悲观锁 乐观锁 池化技术 连接池 Caffeine CP Python Web 崖山 新版本 高可用 向量库 Ftp redo log 重做日志 MCP mini-redis INCR指令 MVCC 事务隔离 磁盘架构 流量 字典 电商 QPS 高并发 单线程 线程 速度 服务器中毒 开放协议 Web 接口 R2DBC 双引擎 RAG HelixDB 原子性 对象 微软 SQL Server AI功能 数据脱敏 加密算法 窗口 函数 主库 Order 频繁 Codis Crash 代码 ZODB SSH 网络 dbt 数据转换工具 1 PG DBA 工具链 引擎 性能 List 类型 Pottery 优化器 InfluxDB 模型 传统数据库 向量化 发件箱模式 意向锁 记录锁 事务同步 网络故障 UUIDv7 主键 Redisson 锁芯 仪表盘 线程安全 INSERT COMPACT Undo Log LLM 订单 JOIN 连接数