mysql解析二进制日志_MySQL二进制日志分析-概述篇

MySQL从3.23版本开始引入了二进制日志,用于的数据复制, 二进制日志根据MySQL的版本不同,目前有4个版本:

https://dev.mysql.com/doc/internals/en/binlog-version.html

690e2ac2293c17934df89fa62cb44f71.png

Version 1: supported statement based replication events.

Version 2: can be ignored as it was only used in early alpha versions of MySQL 4.1.x

and won't be documented here.

Version 3: added the relay logs and changed the meaning of the log position.

Version 4: added the FORMAT_DESCRIPTION_EVENT and made the protocol extensible.

二进制日志版本是向后兼容的, 后一个版本可以看成是对前一个版本的继承和扩展,需要注意的是,version 2是一个临时版本, 可以忽略。事实上可以只关心v4版本,因为现在跑的MySQL都应该是MySQL 5+了,就如现再讨论Oracle 8i, 9i没什么实际意义。截至当前最新的MySQL 8版本,使用的依然是v4版本。

题外话:

BinlogMiner的解析器为保持代码稳定,做了接口将功能和具体实现分隔, 但实际上目前也只有一个BinlogParser4实现。也许以后会有V5版本,还有一个问题就是开源软件的碎片化,目前主流的有3个分支,本人偏爱Percona版本,Percona版本完全兼容官方版本,而在性能和可维护性上有提高,非常讨人喜欢。国内一些大的互联网企业如腾讯,阿里也有做基于MySQL的数据库,目前还没有研究,不知道兼容性如何。

MySQL的二进制日志文件以事件为单位进行封装,文件的结构如下:

1f9d7cae1bff79322bc139e4850a07e6.png

说明:二进制日志可以看成是二进制事件的集合,不同的事件,对应于不同的功能,MySQL包含的事件类型可以参考:

https://dev.mysql.com/doc/internals/en/binlog-event-type.html

A start event (START_EVENT_V3) is the first event of a binlog for binlog-version 1 to 3.

A format description event (FORMAT_DESCRIPTION_EVENT) is the first event of a binlog for binlog-version 4.

v1-v3版本, 二进制日志文件的第一个事件是START_EVENT_V3, 而v4版本开始第一个事件是FORMAT_DESCRIPTION_EVENT,替代掉START_EVENT_V3.

二进制日志的结束事件为STOP_EVENT或者ROTATE_EVENT,出现其中之一就说应二进制文件已经结束, 其中STOP_EVENT说应MySQL服务器已经关闭, 而ROTATE_EVENT则说明二进制达到了max_binlog_size的阈值,或者在线修改了binlog-format,导致了二进制文件的切换。

二进制日志QUERY_EVENT和ROWS_EVENT(包括WRITE_ROWS_EVENT/UPDATE_ROWS_EVENT/DELETE_ROWS_EVENT)来记录数据变化, 所有的DDL,如(create table ...)都是通过QUERY_EVENT记录的, 而DML(inert/update/delete)则根据复制模式的不同(binlog-format)而不同, 基于语句的复制(Statement-Based),DML语句以语句形式记录在QUERY_EVENT中,而基于行的复制(Row-Based Replication),则将受到DML语句影响的行的值,记录在ROWS_EVENT中。显而易见, 基于语句的复制一个明显的优势就是数据量小,delete table xxx,只记录一个语句就可以了,但是行模式则需要记录所有行的值。但如前文说的基于语句的复制不是绝对安全的,当遇到"Nondeterministic"的语句,会由问题,比如SYSDATE(),如果将函数复制到备库执行,得到的结果和主库肯定不一样,又如USER()调用的用户不同,得到的结果也不同。当然可以通过一些选项,在遇到有些函数时转换成函数的结果复制,但并不是说有的函数都能解决,特别是自定义的函数。基于行的赋值,ROWS_EVENT中还包含修改的“前值”,BinlogMiner就是通过这些“前值”达到闪回的效果。

1. magic number

用于表示二进制日志文件, 4个字节长度, 其值为固定的:0xfe 0x62 0x69 0x6e; 紧接着的是一个个的二进制日志事件。二进制日志的每个事件的结构如下:

d6134c55a6633fd7c77f9fac0baf5ca0.png

2. Common Header

通用文件头, 其实定义了一个事件的基本信息, 包含事件的起止位置, 类型, 时间搓和服务器ID等信息, 我们依赖这些信息特别起止位置来遍历整个二进制日志文件,Common Header的结构如下:

https://dev.mysql.com/doc/internals/en/binlog-event-header.html

Binlog header Payload:

4  timestamp

1  event type

4  server-id

4  event-size

if binlog-version > 1:

4 log pos

2 flags

可以看到Common Header的长度是固定的13个字节或者19个字节。只有v1版本是13个字节, 后续的版本都是19个字节, 主要是多了log pos, 也就是当前事件的结束位置, v1版本虽然没有结束位置, 但是是可以通过事件的开始位置 + 事件长度(event-size)计算出来的,之所以称为Common Header,是因为这部分是与具体事件无关的。

3. Post-Header

Common Header后紧跟着的是Post-Header部分, Post-Header是跟具体事件相关的,而且并不是每个事件都有Post-Header(可以为0),Post-Header的长度对于一个MySQL版本是固定的,但不同版本可能不同,每种事件的Post-header的长度在FORMAT_DESCRIPTION_EVENT中有记录。

4. PlayLoad

Post-Header后紧跟着负载(playload), 也就是具体的内容,这部分是不固定长度的,直到事件的结束(也就是Checksum)。

以一个QUERY_EVENT的案例来概览一下Post-header和playLoad:

* QUERY_EVENT: The query event is used to send text querys right the binlog.

*

* References:

* https://dev.mysql.com/doc/internals/en/query-event.html

* https://dev.mysql.com/doc/internals/en/event-data-for-specific-event-types.html

*

* Post-header :

*   4  slave_proxy_id

*   4  execution time

*   1  schema length

*   2  error-code

* if binlog-version ≥ 4:

*     2  status-vars length

*

* Payload:

*   string[$len] status-vars

*    string[$len] schema

*   1 [00]

*   string[EOF] query

5. Checksum

也就是事件的校验值, 在MySQL 5.6.2版本开始引入,5.6.6版本开始默认开启(CRC32), 这部分在事件的结尾处, 目前只支持CRC算法,检验值为4个字节,校验算法在FORMAT_DESCRIPTION_EVENT事件中通过1个字节记录。

https://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#option_mysqld_binlog-checksum

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值