• 深入理解MySQL binlog

深入理解MySQL binlog

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

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 Web 应用 异步数据库 数据同步 ACK 双主架构 循环复制 TIME_WAIT 运维 负载均衡 服务器 管理口 HexHub Docker JumpServer SSL 堡垒机 跳板机 HTTPS 服务器性能 JumpServer安装 堡垒机安装 Linux安装JumpServer SQL 查询 生命周期 Deepseek 宝塔面板 Linux宝塔 锁机制 esxi esxi6 root密码不对 无法登录 web无法登录 行业 趋势 序列 核心机制 Windows Windows server net3.5 .NET 安装出错 HTTPS加密 开源 PostgreSQL 存储引擎 宝塔面板打不开 宝塔面板无法访问 Windows宝塔 Mysql重置密码 机器学习 Redis 查看硬件 Linux查看硬件 Linux查看CPU Linux查看内存 Undo Log 机制 Spring 动态查询 响应模型 Oracle 处理机制 InnoDB 数据库锁 优化 万能公式 连接控制 group by 索引 Serverless 无服务器 语言 监控 无法访问宝塔面板 异步化 ES 协同 技术 openHalo scp Linux的scp怎么用 scp上传 scp下载 scp命令 Postgres OTel Iceberg 工具 缓存方案 缓存架构 缓存穿透 国产数据库 高可用 分页查询 数据 主库 SVM Embedding Linux 安全 SQLite-Web SQLite 数据库管理工具 GreatSQL 连接数 Netstat Linux 服务器 端口 存储 云原生 加密 场景 R edis 线程 R2DBC 防火墙 黑客 Recursive 启动故障 共享锁 SQLark 日志文件 MIXED 3 OB 单机版 向量数据库 大模型 ​Redis 推荐模型 Canal AI 助手 RocketMQ 长轮询 配置 自定义序列化 PG DBA 不宕机 信息化 智能运维 Python 传统数据库 向量化 向量库 Milvus 业务 同城 双活 线上 库存 预扣 Ftp Hash 字段 Web 接口 开发 聚簇 非聚簇 电商 系统 修改DNS Centos7如何修改DNS IT运维 filelock 分库 分表 Rsync 架构 数据类型 MySQL 9.3 磁盘架构 缓存 sftp 服务器 参数 mini-redis INCR指令 MongoDB 数据结构 redo log 重做日志 数据分类 MCP 开放协议 PostGIS • 索引 • 数据库 ZODB Doris SeaTunnel 语句 流量 频繁 Codis 分布式架构 分布式锁​ 窗口 函数 MVCC Go 数据库迁移 虚拟服务器 虚拟机 内存 工具链 人工智能 推荐系统 数据备份 失效 EasyExcel MySQL8 主从复制 代理 Redisson 锁芯 prometheus Alert MGR 分布式集群 分页 聚簇索引 非聚簇索引 高效统计 今天这篇文章就跟大家 千万级 大表 播客 StarRocks 数据仓库 网络架构 网络配置 数据集成工具 引擎 性能 网络故障 崖山 新版本 事务 Java INSERT COMPACT 发件箱模式 容器 Entity 核心架构 订阅机制 QPS 高并发 SSH Redka B+Tree ID 字段 Weaviate RDB AOF 关系数据库 速度 服务器中毒 Web 数据脱敏 加密算法 数据页 Redis 8.0 Caffeine CP Valkey Valkey8.0 DBMS 管理系统 分布式 集中式 OAuth2 Token 自动重启 SpringAI 容器化 模型 微软 SQL Server AI功能 读写 LRU 原子性 排行榜 排序 池化技术 连接池 数据字典 兼容性 JOIN 意向锁 记录锁 事务隔离 dbt 数据转换工具 业务场景 Testcloud 云端自动化 单点故障 UUID ID 分页方案 排版 部署 日志 优化器 1 ReadView Pottery InfluxDB 悲观锁 乐观锁 事务同步 网络 sqlmock UUIDv7 主键 AIOPS 分布式锁 Zookeeper 对象 仪表盘 字典 双引擎 RAG HelixDB 产业链 Order 编程 单线程 Ansible Pump 恢复数据 Crash 代码 LLM 拦截器 动态代理 线程安全 国产 用户 快照读 当前读 视图 IT 订单 List 类型 慢SQL优化 count(*) count(主键) 行数 RR 互联网 表空间 解锁 调优 Next-Key 神经系统 矢量存储 数据库类型 AI代理 CAS 查询规划 多线程 GitHub Git 算法 技巧 并发控制 恢复机制 闪回