mysql中的binlog-介绍

简介

binlog是一个二进制格式的文件,用于记录用户对数据的更新操作,一般来说,开启binlog大概会带来1%的性能损耗。

binlog的使用场景:主从复制、数据恢复

binlog日志中包含日志索引文件和日志文件,日志索引文件用于记录所有的二进制文件,日志文件中记录对数据库的修改操作,包括DML和DDL

查看binlog的配置

在mysql客户端执行如下命令,查看binlog的相关配置

1、查看是否开启binlog: show variables like 'log_bin' ,ON表示已开启

2、查看binlog的相关变量: show variables like '%log_bin%' 、 show variables like '%binlog%'

变量内容讲解:

  • 是否开启binlog

    • log_bin:默认值为ON,表示已开启binlog

    • sql_log_bin:当前会话的binlog记录是否开启,ON是已开启

  • binlog的文件存放位置:

    • log_bin_basename:binlog文件的基础路径,例如 /var/lib/mysql/binlog.000001 等文件
    • log_bin_index:binlog索引文件的路径
  • binlog_format:binlog的日志格式,默认是ROW,共有有三个可选值:

    • ROW:记录每行数据的变化,不记录SQL语句,它的优点是数据安全,缺点是日志文件比较大,不易阅读
    • STATEMENT:记录实际执行的sql语句
    • MIXED:混合模式,大部分使用STATEMENT,特殊情况使用ROW,例如某些根据时间来删除数据的sql,它对于数据库的操作是不稳定的,不同时间执行会获得不同的结果,所以需要使用ROW模式。
  • binlog保留策略的相关配置:

    • binlog_expire_logs_seconds:默认值是2592000,单位是秒,表示30天,表示binlog默认保留30天
    • binlog_expire_logs_auto_purge:值为ON,表示自动清理过期的binlog
  • binlog性能相关配置:

    • max_binlog_size:单个binlog文件最大1GB
    • sync_binlog:每次提交都同步到磁盘,默认中是1
      • 0:由系统决定何时同步
      • 1:每次事务提交都同步(最安全,数据不丢失)
      • N:每N次事务提交同步一次
    • binlog_cache_size:binlog缓存32KB
  • 高级特性:

    • binlog_row_image:FULL,记录完整的行数据
    • binlog_checksum:CRC32,binlog校验算法
    • binlog_row_metadata:MINIMAL,行元数据记录最小化
    • binlog_rows_query_log_events: OFF,不记录原始SQL语句,如果设为ON,会在ROW格式下同时记录原始SQL语句,建议在生产环境设为ON,便于问题排查

总结:从这些配置中,可以看出

  • binlog默认是开启的
  • binlog的存放目录,这里是/var/lib/mysql/
  • binlog的格式,这里是ROW,它记录的sql操作的数据,并且会导致binlog文件比较大
  • binlog的生成,默认每次提交都同步到磁盘,默认保留30天

配置binlog

案例:

text 复制代码
[mysqld]

#配置serverid
server-id=1

这里全部使用binlog的默认配置,只额外配置一个服务器的id,主从同步时需要使用到

配置完成后重启mysql服务:systemctl restart mysqld

介绍binlog中的内容

binlog由一系列事件组成,除了binlog自身独有的事件,例如文件创建、文件轮转,大多数事件都对应了mysql的一条sql。

事件的结构:

  • 事件头:包含事件类型、时间戳、服务器ID等
  • 事件体:事件的具体内容
  • 校验和

binlog中的事件类型:

  • Format_desc事件:binlog文件的开始事件,所有binlog文件都是已这个事件开始的。这个事件记录的信息中包含服务器的版本、binlog版本
  • Previous_gtids事件:记录之前所有binlog文件中的gtid集合
  • Anonymous_Gtid事件:在没有启动GTID时,标识事务开始,
  • Query事件:查询事件
  • Table_map事件:表映射事件,建立表名到内部id的映射,通过这种方式减少数据量
  • Delete_rows事件:删除行,
  • Xid事件:事务提交事件
  • Rotate事件:binlog文件轮转事件,当前binlog文件结束,切换到下一个binlog文件

这里没有列举出全部,还有诸如 Update_rows、Write_rows 等事件

事件的位置:position,相当于这个事件的下标,在文件中唯一标识这个事件,根据它来操作binlog

事件的GTID:Global Transaction Identifier,全局事务标识符,mysql 5.6之后引入的新特性,为每个事务分配一个全局唯一的标识符。GTID默认是关闭的,通过它来指定事件会更方便。

查看binlog中的内容

1、查看当前mysql实例有哪些binlog:show master logs

text 复制代码
+---------------+-----------+-----------+
| Log_name      | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000028 |       377 | No        |
| binlog.000029 |       509 | No        |
| binlog.000030 |       157 | No        |
+---------------+-----------+-----------+

这里共查询到3个binlog文件,包括文件名称、文件大小、是否加密

2、查看当前binlog点位:show master status

text 复制代码
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000030 |      157 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+

这里的内容是最后一个binlog文件的名称、最后一次操作时间的position值

3、查看binlog中的事件:show binlog events in 'binlog.000029';

text 复制代码
+---------------+-----+----------------+-----------+-------------+--------------------------------------+
| Log_name      | Pos | Event_type     | Server_id | End_log_pos | Info                                 |
+---------------+-----+----------------+-----------+-------------+--------------------------------------+
| binlog.000029 |   4 | Format_desc    |         1 |         126 | Server ver: 8.0.38, Binlog ver: 4    |
| binlog.000029 | 126 | Previous_gtids |         1 |         157 |                                      |
| binlog.000029 | 157 | Anonymous_Gtid |         1 |         236 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000029 | 236 | Query          |         1 |         311 | BEGIN                                |
| binlog.000029 | 311 | Table_map      |         1 |         374 | table_id: 97 (blog.ms_tag)           |
| binlog.000029 | 374 | Delete_rows    |         1 |         434 | table_id: 97 flags: STMT_END_F       |
| binlog.000029 | 434 | Xid            |         1 |         465 | COMMIT /* xid=17 */                  |
| binlog.000029 | 465 | Rotate         |         1 |         509 | binlog.000030;pos=4                  |
+---------------+-----+----------------+-----------+-------------+--------------------------------------+

内容解读:这里只做部分介绍,可以在Info列中看到,BEGIN到COMMIT之间,就是一个删除事务,根据binlog来恢复数据,就是以事务为单位的。

3、查看binlog文件中的内容:mysqlbinlog binlog.000029,使用mysqlbinlog命令,进入binlog所在目录,查看文件中的内容,因为是二进制内容,所以要使用mysqlbinlog命令。

文件中,关于sql操作的数据,使用加密的,如果想要查看,需要指定参数:mysqlbinlog --base64-output=DECODE-ROWS -v binlog.000029

原始的sql日志不太好看,有一个关键点,就是找 # at N 的位置,它表示一个事件开始,N是字节偏移

根据binlog恢复数据

根据binlog恢复数据的原理,是通过把binlog中执行的操作全部再执行一次,然后跳过需要被排除的操作,来恢复错误操作带来的影响,同时还要注意,如果binlog因过期等原因被删除,那么通过binlog无法恢复数据。

任意时间点的数据状态 = 基础备份状态 + 从备份时间点到目标时间点的所有变更 - 需要排除的错误变更,所以使用binlog恢复数据,依赖最新备份的数据 + 这之间所有的binlog日期 - 错误变更,或者全量的binlog日志

常见的方式是:定期备份数据,然后清理已备份数据的binlog,如果需要通过binlog来恢复数据,就把数据恢复到最新备份,然后执行最新备份到当前时间的binlog,跳过需要被排除的事务,从而达到恢复操作的目的。

恢复时必须以事务为单位,也就是日志中BEGIN到COMMIT之间的所有操作,是一个单位

恢复数据之前最好备份当前数据,同时停止服务,避免误操作。

方式一

案例:重新执行所有的binlog,跳过需要被排除的事务,通过position来指定需要被排除的事务

text 复制代码
# 应用删除前的操作(4-236)
mysqlbinlog --start-position=4 --stop-position=236 binlog.000029 | mysql -u root -p blog

# 应用删除后的操作(465-509)
mysqlbinlog --start-position=465 binlog.000029 | mysql -u root -p blog

这里只是一个案例,演示一下命令的使用,实际上当前binlog无法恢复数据,因为在删除数据之前,新增数据的binlog已经过期了,所以即使执行当前命令,也无法恢复数据。这里仅仅演示命令的使用。

案例2:通过时间点来指定需要被排除的事务

text 复制代码
mysqlbinlog \
  --start-datetime="2025-12-19 00:00:00" \
  --stop-datetime="2025-12-19 13:56:09" \
  binlog.000029 | mysql -u root -p blog

这里是把数据库中的数据恢复到指定时间点之前,因为在日志中,删除操作在 251219 13:56:10 执行,所以指定一个比它早的时间 "2025-12-19 13:56:09"

方式二

根据binlog,生成相反的操作,然后恢复数据,这需要依赖第三方工具,例如binlog2sql,有时间再介绍

通过binlog同步数据的流程

通过binlog同步数据的流程:

  • 主库写binlog
  • 主库发送binlog,主库会使用一个单独的线程来发送binlog
  • 从库接收binlog,并且把它写入到relay log
  • 从库回放:从库执行relay log中的sql,达到数据同步的目的
相关推荐
likuolei2 小时前
正则表达式 - 元字符
数据库·mysql·正则表达式
少云清2 小时前
【接口测试】4_PyMySQL模块 _操作数据库
服务器·网络·数据库
IndulgeCui2 小时前
Kingbase-金仓企业级统一管控平台KEMCC一键部署主备集群及转换读写分离集群
数据库
数据库生产实战2 小时前
Oracle升级避坑指南:APEX卸载后sys.htmldb_system无效对象的处理方法
数据库·oracle
冰冰菜的扣jio2 小时前
SQL语句是如何在MySQL中执行的
数据库·sql
么么...2 小时前
掌握 MySQL:数据类型、数据定义语言DDL、数据操作语言DML
数据库·经验分享·sql·mysql
蓝影铁哥2 小时前
浅谈5款Java微服务开发框架
java·linux·运维·开发语言·数据库·微服务·架构
马克学长2 小时前
SSM校园公益活动网站7a9p4(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·校园公益活动网站
李慕婉学姐2 小时前
Springboot在线阅读平台的设计与实现5yy58005(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端