MYSQL] binlog校验

 

binlog是什么?

binlog是mysql server层的日志, 一个非常重要的日志,记录用户的各种操作(changes). 默认启用.

binlog有啥用?

  1. 备份恢复: 可以用来恢复数据到任一时间点.(或者异常重启恢复)
  2. 高可用: 也可以用来搭建从库,集群等
  3. 审计: 查看数据的历史变更情况, 但是看不到执行者的IP,只能看到thread-id.

binlog怎么校验是否损坏?

这个是本文重要讨论的, 虽然mysqlbinlog--verify-binlog-checksum选项就能校验binlog是否损坏(其实是写这个工具之前没发现这个参数…).

binlog损坏了怎么办?

凉拌

binlog结构

在讨论校验原理之前, 我们先简单看看binlog的结构:

  1. binlog由若干个event构成.
  2. 每个event由19字节的event_header(9字节)和event_body构成
  3. 第一个event为FORMAT_DESCRIPTION_EVENT, 记录的是binlog版本,mysql版本,checksum算法等信息.
  4. relay log和Binlog格式完全一样. 只不过binlog开头多了4字节的magic(b'\xfebin')
  5. event_header部分 信息为:
对象大小描述
timestamp 4 时间戳
event_type 1 event的类型
server_id 4 serverid
event_size 4 这个event大小(含event_header&checksum)
log_pos 4 结束位置的偏移量
flags 2 一些flag

整体如下

 

校验原理

在FORMAT_DESCRIPTION_EVENT中, 最后的信息是checksum_alg, 表示这个binlog是否有checksum位. 当然前提是参数binlog_checksum的值为CRC32才行. 如果binlog_checksum未设置校验的话, 是无法校验Binlog的. 我们这里就只讨论存在校验的情况.

有些情况可能会关闭binlog校验, 比如MGR

既然要校验, 那么肯定得每个event都校验,比较不可能文件写完之后才校验,那样就没得校验的意义了. 由于是server层实现的, 校验的算法通常就是crc32 (innodb使用的是crc32c).

那么这个校验值应该存储在哪呢? 最简单的就是存储在event结尾处. 出于兼容性考虑, event_header记录的大小/pos应该包含这4字节. 于是得到如下结构:

我们要校验的时候, 也只需要将event_header+event_body的crc32校验值和记录的crc32校验值比较即可确定event是否损坏.

设计思路

既然知道该校验信息了, 那么就来设计个binlog的校验工具吧.

选语言: 我们使用python编写, 这样开发效率最高, 而校验主要是涉及到文件读取和crc32计算,这2者在编程语言之间差距不大(有时候感觉还挺快的)

兼容性: 使用者可能是python2或者python3环境, 所以我们需要考虑py2和py3的兼容性. 使用者可能是5.7, 8.0, 8.4环境, 所以还需要考虑mysql的兼容性. 还得同时支持binlog和relay log(就4字节的差)

使用: 由于功能单一, 不需要复杂的参数, 所以直接使用位置参数即可. 而使用者可能还想一次性校验多个文件, 所以还得考虑多个文件的情况, 而且文件可能有不存在的情况.

校验: 遇到坏的event之后, 就不应该继续校验了, 毕竟无法确定event的哪部分是损坏的, 也就无法确定下一个event的位置

说得比较简洁, 有些问题只有实际写的时候才会遇到, 比如: py2使用binascii.crc32校验的结果是有符号的(范围-2**31, 2**31-1), 而py3使用binascii.crc32校验的结果是无符号的(范围0, 2**32-1), 这种问题很多情况发现不了, 只有足够多的数据量(或者运气好)才能发现. 当然解决办法比较简单, 直接将结果&0xffffffff即可变成无符号的整数

验证

我们就简单验证下效果

总结

  1. 在这个脚本写完之后,准备总结下的时候才发现其实官方也支持binlog的校验(--verify-binlog-checksum), 不过之前没有发现而已, 因为之前解析的时候有问题会直接报错的, 而这次没有报错出来, 就以为没得这个功能. 于是就重新写了一版(所以是v2)
  2. 对于损坏的binlog,如果是从库,可以重建; 如果是主库呢?(只要数据提交了, 数据库没挂, 貌似就没得影响…)

转载于:https://mp.weixin.qq.com/s/FdtIGG0dFW8VxoOZiV18nQ

参考:
https://dev.mysql.com/doc/refman/8.0/en/binary-log.html
https://dev.mysql.com/doc/refman/8.0/en/group-replication-limitations.html
https://docs.python.org/zh-cn/2.7/library/binascii.html#module-binascii

相关脚本源码地址: 

https://github.com/ddcw/ddcw/blob/master/python/check_binlog_v2.py

posted @ 2025-06-08 16:01  Harda  阅读(20)  评论(0)    收藏  举报