• 深入理解MySQL binlog

深入理解MySQL binlog

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

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