1、Binlog基础入门:MySQL Binlog是什么、Binlog的三种格式、如何开启Binlog

大家好,欢迎来到《Binlog解析与实时数据捕获》的第一章。

说实话,我刚开始接触MySQL的时候,对Binlog这东西完全没概念。那时候觉得,数据库能跑就行,日志什么的,关掉还能省点磁盘空间。直到有一次,线上数据库出了故障,需要做时间点恢复,才发现没开Binlog——那叫一个后悔。

从那以后,我养成了一个习惯:任何生产环境的MySQL,必须开启Binlog。今天咱们就来聊聊,Binlog到底是什么,它有哪些格式,以及怎么把它打开。

1.1 Binlog是什么?

Binlog,全称Binary Log,也就是二进制日志。它记录了MySQL数据库所有数据变更的操作,比如INSERT、UPDATE、DELETE,还有表结构变更的DDL语句。

你可以把它想象成一个“黑匣子”。数据库里发生的每一次写操作,都会被记录下来。这个黑匣子有什么用呢?

  • 数据恢复:当数据库崩溃,或者误删了数据,可以用Binlog把数据恢复到某个时间点。
  • 主从复制:主库把Binlog发给从库,从库照着执行一遍,就能保持数据一致。
  • 实时数据捕获(CDC):这也是咱们这门课的核心。通过解析Binlog,可以实时获取数据库的变更事件,然后同步到其他系统,比如缓存、搜索引擎、数据仓库。

核心要点:Binlog记录的是“逻辑变更”,而不是物理数据页的变化。这意味着,即使MySQL的存储引擎不同(比如InnoDB和MyISAM),Binlog的格式是一致的。

我个人习惯把Binlog看作是MySQL的“操作日志”。它不记录SELECT查询,只记录那些真正改变了数据的操作。这一点很重要,你想想看,如果连查询都记,那日志量得有多大?

1.2 Binlog的三种格式

MySQL提供了三种Binlog格式:STATEMENT、ROW和MIXED。每种格式都有自己的特点和适用场景。我在项目中踩过不少坑,下面逐一给你讲讲。

1.2.1 STATEMENT格式

STATEMENT格式,记录的是SQL语句本身。比如你执行了一条UPDATE users SET age=age+1 WHERE id=100,Binlog里就原封不动地记下这条SQL。

优点:日志量小,因为一条SQL可能影响很多行,但只记一条记录。

缺点:有些SQL是不确定的。比如用了NOW()、RAND()这些函数,或者用了LIMIT但没有ORDER BY,在主库和从库上执行的结果可能不一样。

我曾经踩过的坑:有一次做主从切换,发现从库的数据和主库对不上。排查了半天,发现是因为业务代码里用了UPDATE ... ORDER BY ... LIMIT 1,没有指定明确的排序规则,导致主从执行结果不一致。从那以后,我坚决不在生产环境用STATEMENT格式。

1.2.2 ROW格式

ROW格式,记录的是每一行数据的具体变化。比如你更新了100行数据,Binlog里就会记录这100行数据更新前和更新后的值。

优点:最安全、最精确。无论SQL怎么写,ROW格式都能保证主从数据完全一致。

缺点:日志量巨大。尤其是批量操作,比如一次更新10万行,Binlog会膨胀得很厉害。

不过,对于CDC场景来说,ROW格式是首选。为什么?因为我们需要知道每一行数据具体变成了什么样子。STATEMENT格式只给了一条SQL,你没法直接拿到变更后的数据值。

我的建议:如果你要做实时数据捕获,或者对数据一致性要求极高,直接用ROW格式。磁盘空间便宜,但数据不一致的代价很昂贵。

1.2.3 MIXED格式

MIXED格式,是STATEMENT和ROW的混合体。MySQL会自动判断:如果SQL是确定的,就用STATEMENT格式记录;如果SQL是不确定的,就自动切换成ROW格式。

听起来很智能,对吧?但实际用起来,有时候会有点“神经质”。MySQL的判断逻辑并不总是符合我们的预期。比如某些存储过程、触发器,MySQL可能会统一用ROW格式记录,导致日志量比预期大。

下面这个表格,可以帮你快速对比三种格式:

格式 记录内容 日志大小 数据一致性 CDC适用性
STATEMENT SQL语句 小 低(可能不一致) 不适用
ROW 行数据变更前后 大 高(完全一致) 首选
MIXED 自动判断 中等 较高 视情况

1.3 如何开启Binlog?

开启Binlog其实很简单,就是修改MySQL的配置文件。但有几个细节需要注意,我带你一步步来。

1.3.1 修改配置文件

MySQL的配置文件通常是my.cnf(Linux)或my.ini(Windows)。在[mysqld]部分,添加以下配置:

[mysqld]
# 开启Binlog
log-bin=mysql-bin

# 设置Binlog格式为ROW(强烈推荐)
binlog-format=ROW

# 设置服务器ID,主从复制时必须唯一
server-id=1

# 可选:设置Binlog保留天数
expire-logs-days=7

# 可选:设置单个Binlog文件大小上限
max-binlog-size=1G

配置说明:

  • log-bin=mysql-bin:指定Binlog文件的前缀。MySQL会生成类似mysql-bin.000001、mysql-bin.000002这样的文件。
  • binlog-format=ROW:设置格式为ROW。我个人习惯,只要不是特殊场景,一律用ROW。
  • server-id=1:每个MySQL实例必须有一个唯一的server-id。如果要做主从复制,主库和从库的server-id不能相同。
  • expire-logs-days=7:自动清理7天前的Binlog,防止磁盘被写满。
  • max-binlog-size=1G:每个Binlog文件达到1G时,自动切换到下一个文件。

1.3.2 重启MySQL服务

修改完配置文件,需要重启MySQL服务才能生效。

# Linux系统
systemctl restart mysqld

# 或者
service mysql restart

1.3.3 验证Binlog是否开启

重启后,登录MySQL,执行以下命令验证:

-- 查看Binlog是否开启
SHOW VARIABLES LIKE 'log_bin';

-- 查看Binlog格式
SHOW VARIABLES LIKE 'binlog_format';

-- 查看当前Binlog文件列表
SHOW BINARY LOGS;

如果log_bin的值为ON,说明开启成功。你还会看到类似mysql-bin.000001这样的文件列表。

一个小技巧:如果你不想重启MySQL,可以在运行时动态修改Binlog格式(但无法动态开启Binlog本身):

SET GLOBAL binlog_format = 'ROW';

不过要注意,这个设置只对新的连接生效,已有的连接还是用旧的格式。

1.4 本章知识体系总览

下面这张图,帮你把本章的核心知识点串起来:

Binlog基础入门 · 知识体系 MySQL Binlog Binlog是什么? 记录所有数据变更的二进制日志 三种格式 STATEMENT ROW(推荐) MIXED 如何开启? 修改 my.cnf 重启MySQL 验证:SHOW VARIABLES 核心建议:生产环境使用 ROW 格式 CDC场景必须使用 ROW 格式

1.5 本章小结

好了,咱们来捋一捋今天的内容:

  • Binlog是什么:MySQL的二进制日志,记录所有数据变更,用于恢复、复制和CDC。
  • 三种格式:STATEMENT(记SQL,日志小但不安全)、ROW(记行数据,最安全但日志大)、MIXED(自动判断,但不可控)。
  • 如何开启:修改my.cnf,设置log-bin、binlog-format、server-id,重启后验证。

我个人强烈建议,除非你有非常特殊的理由,否则生产环境一律使用ROW格式。尤其是咱们这门课后面要讲的CDC实战,ROW格式是基础中的基础。