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 本章知识体系总览
下面这张图,帮你把本章的核心知识点串起来:
1.5 本章小结
好了,咱们来捋一捋今天的内容:
- Binlog是什么:MySQL的二进制日志,记录所有数据变更,用于恢复、复制和CDC。
- 三种格式:STATEMENT(记SQL,日志小但不安全)、ROW(记行数据,最安全但日志大)、MIXED(自动判断,但不可控)。
- 如何开启:修改
my.cnf,设置log-bin、binlog-format、server-id,重启后验证。
我个人强烈建议,除非你有非常特殊的理由,否则生产环境一律使用ROW格式。尤其是咱们这门课后面要讲的CDC实战,ROW格式是基础中的基础。