MySQL之BinLog


朋友们,MySQL能成为当今是最流行的开源关系型数据库,BinLog可以说功不可没,主从同步和数据恢复都依赖它,下面我们对BinLog简要说明。

概念

全名是Binary Log,即二进制日志文件。Binlog 是 Server 层的日志,它记录了所有的 DDL 和 DML(不包含数据查询语句)语句,是以事件形式记录的,还包含语句所执行的消耗的时间等。

BinLog是逻辑日志(仔细想想也是,由于它用于主从同步,主从的数据页可能是不一致的,无法记录数据页的变化,只能记录数据的逻辑变化)。开启 binlog 之后,大致会有 1% 的性能损耗,不过这还是可以接受的,一般来说,binlog 有两个重大的使用场景:MySQL 主从复制 和MySQL 数据恢复。

binlog 是追加写,文件写满(默认1GB)后会自动切换到下一个日志文件继续写。binlog默认在data目录里,mysql-bin.00000n 存储实际的数据库更改事件,mysql-bin.index是binlog索引文件。

MySQL之BinLog


格式

binlog 日志有三种格式,分别为 STATMENT 、 ROW 和 MIXED。

ROW:基于行的复制,记录哪条数据被修改了(不记录每条SQL语句的上下文信息)。

  • 优点:兼容性好;从库无需扫描直接定位更新往往比较快。
  • 缺点:批量修改时会产生大量的日志。

STATMENT:基于SQL语句的复制,记录修改的SQL语句 。相对于ROW模式,STATEMENT模式下只会记录这个 update 的语句,所以此模式下会超级节省日志空间,也避免着大量的IO操作。

  • 优点:不需要记录每一行的变化,减少了 binlog 日志量, 从而提高了性能。
  • 缺点:在某些情况下会导致主从数据不一致,列如执行sysdate() 等 ;主从都需要扫描,两者锁表时间几乎一样长。

MIXED:STATMENT 和 ROW 的混合模式,可以说不是一种新格式。


文件清理

binlog是保存在磁盘上的,会占用磁盘空间,为了避免磁盘占满MySQL支持自动清理和手动清理;

自动清理

binlog有‘过期’这个概念,对过期文件的自动清理由如下几个触发点:

  • MySQL服务重启;一般会生成新的binlog文件,触发过期文件清理。
  • 手动刷新日志;执行命令flush binary logs 和 flush logs 时生成新的binlog文件 ,触发过期文件清理。
  • 自动刷新日志;当前日志文件大小达到 max_binlog_size 值 (默认1GB)时生成新的binlog文件,触发过期文件清理。

但是,上面的触发过期文件清理只是“触发”不是真正的“清理”, 是否真正清理还要满足如下:


binlog_expire_logs_auto_purge=ON;表明开启过期文件自动清理。


binlog_expire_logs_seconds不等于0;0表明永远不过期,大于0表明有具体的过期时间(MySQL5.7之前是expire_logs_days)。

手动清理

进入MySQL执行

# 恢复到初始只有 mysql-bin.000001的状态
reset master;  

# 删除mysql-bin.000003之前的所有binlog
purge binary logs to 
 'mysql-bin.000003'; 

# 删除2025-11-12 14:53:10之前的所有文件
purge binary logs before 
 '2025-11-12 14:53:10'; 

# 产生新的binlog文件
flush binary logs;

查看binlog

binlog是二级制文件直接打开看不懂,可以通过MySQL自带的mysqlbinlog命令查看。

# 查看binlog文件列表(SQL命令)
show binary logs;

# 查看某binlog文件
mysqlbinlog -v mysql-bin.000001

# 查看某binlog文件中数据库bee的信息
mysqlbinlog -v --database=bee 
 mysql-bin.000001

# 解析指定时间范围内的 binlog(不如根据position定位)
mysqlbinlog 
  --start-datetime="2025-11-12 10:00:00" 
  --stop-datetime="2025-11-12 11:00:00" 
  mysql-bin.000001
 
# 解析指定位置范围内的 binlog(超级好用)
mysqlbinlog 
  --start-position=123 
  --stop-position=789 
 mysql-bin.000001

# 解析binlog,内容输出到指定文件
mysqlbinlog mysql-bin.000001 
 > output.sql

# 从mysql-bin.000002开始,一直读取到最后一个binlog文件
mysqlbinlog --to-last-log 
 mysql-bin.000002

# 解析binlog并执行
mysqlbinlog --skip-gtids 
 mysql-bin.000005 | 
 mysql -uroot -p

# 指定第一个文件的开始位置和最后一个文件的
# 结束位置,批量解析并执行(超级方便)
mysqlbinlog --skip-gtids 
  --start-position=193 
  -stop-position=462  
  mysql-bin.000003 
  mysql-bin.000004 
  mysql-bin.000005 | 
  mysql -uroot -p

根据position解析binlog

要解析 insert into emp(name) values('bbb') 对应的部分,怎么确定start-position和stop-position呢?步骤如下:

1、使用 mysqlbinlog -v mysql-bin.00000n 命令解析出可识别的binlog。binlog内容看着许多,实则多半是注释和无需关注的,只关注我们需要的即可。

3、DML都是有事务的,会被 BEGIN 和 COMMIT包括着(DDL没有事务);找到对应的INSERT语句,从SQL处往上找到最近的BEGIN,继续往上找最近的at * 找到 497,也就是 start-position就是497;从SQL处往下找到最近的COMMIT,继续往下找最近的at * 找到691,也就是 stop-position就是691;则得到完整的命令为:

mysqlbinlog –start-position=497 –stop-position=691 mysql-bin.000001

MySQL之BinLog


关键参数

log_bin

说明:是否开启binlog。

可选值:ON:开启;OFF:不开启。为了数据恢复和主从同步提议开启。

binlog_format

说明:binlog日志格式。

可选值:

  • Statement:每一条修改数据的SQL都会记录 binlog 。
  • Row:不记录SQL 语句上下文信息,仅保存哪条记录被修改。
  • Mixed(Mixed-Based Replication,MBR):Statement 和 Row 的混合体。

binlog_expire_logs_seconds

说明:binlog过期时间,单位秒,0表明永远不过期,大于0表明具体的过期时间。

mysql8之前是 expire_logs_days,单位天。

binlog_expire_logs_auto_purge

说明:binlog过期清理。

可选值:ON:过期自动清理 ,OFF:过期不自动清理,提议设置ON。

要和
binlog_expire_logs_seconds配合,只有
binlog_expire_logs_seconds>0且
binlog_expire_logs_auto_purge=ON 才会触发过期文件自动清理。

binlog_cache_size

说明:binlog的内存缓冲区的大小。

默认32KB,提议设置2~4M。

max_binlog_size

说明:每隔binlog文件的的大小。

默认1G。

sync_binlog

说明:BinLog落盘机制。

可选值:

0:事务提交后,数据只write到OS_Cache但不sync盘(等OS sync盘),最高效;

1:数据write到OS_Cache并立即sync盘,最安全;

n(n>1):数据write OS_Cache但不sync盘,每n个事务sync盘一次,折中方案;

提议平时设置 1。

平时说的双一是指 sync_binlog 和
innodb_flush_log_at_trx_commit 均设置为 1。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容