Mysql杂志(三十五)——Bin log
我们这篇来讲讲Binlog,马上Mysql篇的内容就说干净了,还是蛮激动的兄弟们。
Binlog
Binlog可以说是修改日志也可以叫审计日志,反正他是记录Mysql数据库中所有的DDL、DML操作,通过这个日志我们可以实现主从复制、备份等操作的重要手段,我们每次启动Mysql都会生成一个对应的Binlog日志,所以可以看到我们有些Binlog大有些小的原因。然后每个Binlog文件的最大内存大小默认是1G,但是这个并不是很严格,也就是可能超过这个大小。因为我们BInlog记录是以事务为单位的,所以记录起来要么整个事务记录下来,要么不记录,所以可能超过文件最大设置,但是这个超过的事务一旦记录完就会换下一个Binlog日志文件再进行记录。
我们使用这个命令可以查看关于binlog都有哪些系统变量。有37个主包挑其中几个来说吧,一个一个说篇幅太长了。
SHOW VARIABLES LIKE '%bin%';
| 变量名 | 默认值 | 作用说明 | 版本要求 |
|---|---|---|---|
|
| OFF(5.7-)/ON(8.0+) | Binlog总开关 | 全版本 |
| log_bin_basename | /var/lib/mysql/binlog | Binlog 文件的基础路径和名称前缀(不包含数字后缀) | 5.6+ |
| log_bin_index | /var/lib/mysql/binlog.index | 记录所有 Binlog 文件列表的索引文件路径 | 5.6+ |
| log_bin_trust_function_creators | OFF | 是否信任存储函数创建者(启用后允许非 SUPER 权限用户创建存储函数) | 全版本 |
| sql_log_bin | ON | 会话级 Binlog 开关,控制当前会话的操作是否记录到 Binlog | 全版本 |
|
| ROW(8.0+) | 格式(ROW/STATEMENT/MIXED) | 全版本 |
|
| FULL | 行记录模式(FULL/MINIMAL/NOBLOB) | 5.6+ |
|
| 1 | 刷盘策略(0-N),表示几次事务提交刷盘一次,0表示由操作系统决定刷盘时机 | 全版本 |
|
| 1G | 单个文件最大值 | 全版本 |
|
| 2592000(30天) | 自动清理时间 | 8.0+ |
|
| 32K | 未提交事务缓存大小 | 全版本 |
|
| 0 | 组提交延迟(微秒) | 5.7+ |
|
| OFF | Binlog加密 | 8.0.14+ |
|
| NULL | JSON处理优化 | 8.0.20+ |
|
| COMMIT_ORDER | 并行复制控制 | 8.0+ |
binlog_format格式
有三种格式对比表格如下,ROW是记录修改的行记录,优点就是可靠性高只要行被修改了新增了都会把完整的行记录写入binlog文件中,而且主从复制的从表不需要大量的锁,缺点也很明显就是需要很大的空间,因为相对于STATEMENT来说可能是一行SQL但是ROW可能就是几百上千行记录。而STATEMENT的优点就是空间要求小,但是会占用大量的锁因为一条语句并不确定多少行所以可能会直接把表锁了,而且一些不确定函数可能数据又不一样,最简单的就是NOW()函数,而这个MIXED就是把不确定的因素的修改使用ROW,而确定性的就使用STATEMENT格式,但是因为混合使用的可靠性就是中等了。
| 特性 | ROW格式 | STATEMENT格式 | MIXED格式 |
|---|---|---|---|
| 记录内容 | 行数据变更 | 原始SQL语句 | 智能混合 |
| 可靠性 | 最高 | 最低 | 中等 |
| 日志量 | 最大 | 最小 | 中等 |
| 适用场景 | 金融/交易 | 报表/日志 | 通用业务 |
binlog_row_image格式
binlog_row_image是控制 InnoDB 行级变更在二进制日志(Binlog)中记录方式 的核心参数,它决定了在 ROW 格式的 Binlog 中如何记录被修改行的数据内容。
也就是说这个属性只有在binlog_format设置为ROW的时候才有用,当然了Mysql8之后默认都是ROW格式了。
FULL是记录修改前这行数据已经修改后的这行数据,也就是前后镜像,这样当然是最安全的同时也是空间使用最多的,这个是默认的
MINIMAL记录的就是修改列的数据和主键的值,也就是ID+修改列内容。
NOBLOB这个就是记录除了BLOB属性的列外的所有列,这个BLOB一般都是图片、音频之类的列。
| 模式 | 记录内容 | 日志大小 | 安全等级 | 适用场景 |
|---|---|---|---|---|
| FULL | 所有列值(前镜像+后镜像) | 最大 | ★★★★★ | 金融/强一致需求 |
| MINIMAL | 仅变更列+唯一键 | 最小 | ★★★ | 高并发写入场景 |
| NOBLOB | 除BLOB外全列 | 中等 | ★★★★ | 含文本的常规业务 |
怎么查看binlog日志
查看binlog日志的方式有很多种,但是主要还是使用mysqlbinlog工具和SHOW BINLOG EVENTS命令去查看,所以主包这里就主要说一下这俩。
mysqlbinlog查看
需要注意的是这个命令是需要在服务器命令行中使用的(不用登录mysql,直接在Linux中打命令就可以),我们平常使用的回话以及一些查询窗口是不支持这个命令的,因为他是mysql的一个工具。
mysqlbinlog /var/lib/mysql/mysql-bin.000001
我们可以先通过以下两个命令定位一下需要查询的文件。
查看所有binlog文件
SHOW BINARY LOGS;
查看当前使用的是那个文件
SHOW MASTER STATUS;
这个是一些常用的一些命令
# 查看特定位置的日志
mysqlbinlog --start-position=120 --stop-position=500 mysql-bin.000001# 查看特定时间段的日志
mysqlbinlog --start-datetime="2023-08-15 09:00:00" --stop-datetime="2023-08-15 10:00:00" mysql-bin.000001# 解码ROW格式的日志
mysqlbinlog -v --base64-output=DECODE-ROWS mysql-bin.000001# 显示原始SQL语句
mysqlbinlog --base64-output=DECODE-ROWS --verbose mysql-bin.000001

这个就是解码后的文本样式,这些关键词我们等下说基本上和show一样的,如果我们不小心删除或者修改了一些数据,那么我们如何进行恢复呢?有以下几种方式:
# 恢复到特定时间点之前
mysqlbinlog --start-datetime="2023-08-15 09:00:00" \--stop-datetime="2023-08-15 10:00:00" \/var/lib/mysql/binlog.000234 | mysql -u root -p
# 恢复到特定位置
mysqlbinlog --start-position=445885806 \--stop-position=445887484 \/var/lib/mysql/binlog.000234 | mysql -u root -p
# 跨多个文件恢复
mysqlbinlog --start-position=445885806 \/var/lib/mysql/binlog.000234 \/var/lib/mysql/binlog.000235 | mysql -u root -p
# 只恢复特定数据库和表
mysqlbinlog --database=zentao \--table=zt_config \/var/lib/mysql/binlog.000234 | mysql -u root -p
# 排除某些表
mysqlbinlog --exclude-database=mysql \/var/lib/mysql/binlog.000234 | mysql -u root -p
# 生成反向SQL(用于撤销误操作)
mysqlbinlog --flashback \--start-position=445885806 \--stop-position=445887484 \/var/lib/mysql/binlog.000234 > rollback.sql# 检查回滚SQL
cat rollback.sql
# 执行回滚
mysql -u root -p < rollback.sql
如果要回滚某一个文件最好是先重新开一个binlog文件,保证上一个文件不被污染,因为恢复的时候也会生成binlog文件。
-- 立即创建新的Binlog文件
FLUSH BINARY LOGS;
SHOW BINLOG EVENTS IN '文件名' FROM POS起始位置 LIMIT 1000;
这个是可以在工具中使用的命令,所以内容就没有命令行来的多,但是基本的都有了。而且功能没有那么多,恢复数据的话还是需要使用mysqlbinlog这个工具的。

| 字段名 | 数据类型 | 作用说明 | 示例值 | 计算关系 |
|---|---|---|---|---|
|
| VARCHAR(255) | Binlog文件名 |
| - |
|
| BIGINT | 事件起始位置(字节) |
| 事件大小 = |
|
| BIGINT | 事件结束位置(字节) |
| 下一个事件 |
| Server_id | INT | 服务器唯一标识 | 1 | 防止循环复制,主从识别 |
| CRC32 | VARCHAR(16) | 校验和验证 | 0x032c73c8 | 数据完整性检查 |
event_type字段的内容:
| 元数据事件 | |||
|---|---|---|---|
| Event_type | 作用 | Info内容示例 | 出现位置 |
|
| Binlog文件头信息 |
| 文件开头 |
|
| 之前GTID集合 | (空) | 文件开头 |
| 事务控制事件 | |||
|---|---|---|---|
| Event_type | 作用 | Info内容示例 | 事务阶段 |
|
| 匿名事务标识 |
| 事务开始前 |
|
| SQL语句执行 |
| 事务开始/结束 |
|
| 事务提交 |
| 事务提交时 |
| 数据操作事件 | |||
|---|---|---|---|
| Event_type | 作用 | Info内容示例 | 数据变更类型 |
|
| 表结构映射 |
| DML操作前 |
|
| 插入数据 |
| INSERT操作 |
|
| 更新数据 |
| UPDATE操作 |
|
| 删除数据 |
| DELETE操作 |
删除binlog文件
这个一般来说用不着,而且也不建议,因为mysql自己会删除,删除的风险还是非常大的,除非真想删库跑路了。这边这是介绍并不建议使用哈。
-- 删除指定时间之前的Binlog文件
PURGE BINARY LOGS BEFORE '2023-08-15 00:00:00';-- 删除到指定文件之前的所有文件(保留该文件)
PURGE BINARY LOGS TO 'binlog.000235';-- 删除所有Binlog文件并重置序号(慎用)
RESET MASTER;
总结
本篇主要讲的就是binlog的一些参数,以及如何查看binlog日志,包括如何恢复和删除binlog日志。
