Mysql binlog 解析

首先,我们知道MySQL本身就带有replication的机制,我们需要伪造一个slave,向master注册,这样的话master才会发送binlog event。注册很简单,通过调用limysql.so中的cli_advanced_command(),指定binlog filename+position,向master发送COM_BINLOG_DUMP命令。在发送dump命令的时候,我们可以指定flag为BINLOG_DUMP_NON_BLOCK,这样master在没有可以发送的binlog event之后,就会返回一个EOF的包。数据包的具体格式如下:

例如COM_BINLOG_DUMP类型的数据包payload(数据包体)是这样的:

3.1.2 接收事件

通过调用libmysql.so库中的cli_safe_read()函数,获得master发过来的数据,每次获得一个事件记录的数据,cli_safe_read()的返回值标示了从master发送过来的数据的数据字节数。而发送过来的数据保存在mysql->net->read_pos数组中。

3.2 Binlog事件

通过调用libmysql.so库中的cli_safe_read()函数可以获取一次binlog事件。

MySQL的Binlog事件类型有27种,在MySQL5.6之后增加到38种,但是我们只介绍与ROW模式相关的事件,所有的event都含有如下通用的事件结构:

+===============================+

|      event header   |

+===============================+

|   event data     |

+===============================+

分别为事件头和事件体组成,而事件的内部结构随MySQL版本的不同而变化着,我们需要用到的版本为v4,用于mysql5.1及以上,其他版本就不做介绍了,想要了解的朋友可以参考官方文档。下图为v4版本的event header格式。

由于各个事件的事件头一致,这里我们就不重复介绍了,后面各个事件我们也将忽略对事件头字段的描述。

 

3.2.1 ROTATE_EVENT

ROTATE_EVENT,   记录了接下来要请求的binlog的信息。格式如下:

它里面其实就是标明下一个event所在的binlog filename和position。这里需要注意的是,当slave发送binlog dump之后,master会首先发送一个ROTATE_EVENT,用来告知slave下一个event所在的位置,然后才跟着其他事件。

3.2.2 QUERY_EVENT

QUERY_EVENT, 存储的是SQL,主要是一些与数据无关的操作,如begin,alter table,drop table,create table等。格式如下

  3.2.3 TABLE_MAP_EVENT

TABLE_MAP_EVENT,记录了某个table所对应的表信息,在其中存储了数据库名和表名等。格式如下:

在这个事件中我们需要注意的是,虽然我们可以用表的id标识符table_id来代表一个特定的表,但是因为alter table或rotate binlog event等原因,master会改变某个table的table_id,所以我们在外部不能使用这个table_id来索引某个table。

还需要关注的就是里面的column meta信息,后续我们解析ROW_EVENT的时候会根据这个来处理不同类型的数据。

3.2.4 ROWS_EVENT   

ROWS_EVENT,包含了insert,update,以及delete三种event,并且有v0,v1,v2三个版本。ROWS_EVENT的基本格式如下:

在这里MySQL5.6开始event的type发生变化了,所以MySQL5.6需要改一下,

所以为了我们软件的版本兼容性,我们需要在软件中支持不同的版本。

MySQL5.1~MySQL5.6

·        TABLE_MAP_EVENT:19

·        WRITE_ROWS_EVENT: 23

·        UPDATE_ROWS_EVENT: 24

·        DELETE_ROWS_EVENT:  25

MySQL5.6以上

·        TABLE_MAP_EVENT:19

·        WRITE_ROWS_EVENT: 30

·        UPDATE_ROWS_EVENT: 31

·     DELETE_ROWS_EVENT:  32

ROWS_EVENT的table_id跟TABLE_MAP_EVENT一样,虽然table_id可能变化,但是ROWS_EVENT和TABLE_MAP_EVENT的table_id是能保证一致的,所以我们也是通过这个来找到TABLE_MAP_EVENT的。

为了节省空间,ROWS_EVENT里面对于各列状态都是采用bitmap的方式来处理的。首先我们需要得到column present bitmap的数据,这个值用来表示当前列的一些状态,如果没有设置,也就是某列对应的bit为0,表名该ROWS_EVENT里该列的数据,外部用null代替就可以了。

然后就是每个record里的bitmap,这个是用来表明一行实际的数据里面有哪些列是NULL的,如果该列为NULL,则为1。

在得到column_bitmap和null_bitmap后,我们就可以实际解析这行对应的数据了,对于每一列,首先判断是否column_bitmap标记了,如果为0,这跳过用null表示,然后再看是否null_bitmap里面标记了,如果为1,则表明为null。

但是,因为我们得到的是一行数据的二进制流,又如何将一列数据解析出来呢,这里就需要靠TABLE_MAP_EVENT里的column_meta了。Column_def中定义了该列的数据类型,对于一些特定的类型,譬如MYSQL_TYPE_LONG,MYSQL_TYPE_TINY等,长度都是固定的,所以我们可以直接读取对应长度的数据得到实际的值,但对于一些类型,则没有这么简单。这时候就需要通过meta来辅助计算了。举个例子:

MYSQL_TYPE_BLOB类型,meta为1表示的为tinyblob,第一个字节解释blob的长度,2表名的是shortblob,前两个字节为blob的长度等,而对于MYSQL_TYPE_VARCHAR,meta存储的则是string的长度,下一小节我们介绍每一种类型的计算方法。

3.2.5 XID_EVENT

XID_EVENT一般出现在一个事务操作之后或者其他语句提交之后。它的主要作用提交事务操作和把事件刷新至binlog文件中。里面存的是8个字节的事务ID号。

3.3 不同的数据类型的长度

上一节我们介绍了在不同事件的事件格式以及需要注意的事项,在其中ROWS_EVENT事件中,在record中bit_map之后的列数据中,针对不同的数据类型,可能在record中占用不同的字节,因从需要针对每种数据类型进行处理,

下面列出大部分常用数据类型的字节数和解析方法:

3.3.1 MYSQL_TYPE_INT家族

3.3.2 MYSQL_TYPE_DOUBLE家族

MYSQL_TYPE_NEWDECIMAL类型

声明语法为decimal(M,D),decimal参量的取值范围如下:

M为数字的最大数(精度),其范围为1~65,默认为10

D是小数点后面的数目(标度)。范围为0~30,但不得超过M

table_map_event中的metadata为2个字节,它会记录该类型的精度和标度,其中第一个字节表示精度,第二个字节表示精度。那么数据的长度是如何计算的呢?

比如说decimal(15,5)a=1234567890.12345,那么a的精度为15,标度为5,所以a的整数位最多为10,mysql中每9个数字用一个32位4个字节的整形来存储,剩下不够9个字节的按照如下方式:

intdig2byte[10] = {0,1,1,2,3,3,3,4,4,4};

该数组表示剩下几个字节的数字用几个字节存储。为什么这样做呢,我们知道一个int型变量能存储的最大整数位2^32,是一个十位数的整数,所以最多可以表示9位数的数字。binlog中的decimal按照小数点前后分别存储,所以a的整数位需要2个int型来存储,小数后的计算方式也一样,需要3个字节存储,所以decimal(15,5)在binlog中需要11个字节来存储数据

3.3.3 MYSQL_TYPE_STRING

处理该类型数据时,需要利用metadata辅助计算,metadata的前一个字节表示类型,后一个字节表示长度,如果类型为MYSQL_TYPE_SET和MYSQL_TYPE_EUM时,数据的长度则为后一个字节的大小。如果类型为

MYSQL_TYPE_STRING,第一个字节的数字即为该类型数据的长度。

3.3.4 MYSQL_TYPE_BIT

查看mysqlcapture实现代码

3.3.5 MYSQL_TYPE_DATA家族

3.3.6 MYSQL_TYPE_BLOB家族

Metadata为1,第一个字节表示长度,metadata为2,前两个字节表示长度,metadata为3,前三个字节表示长度,metadata为4,前四个字节表示长度。

3.3.7MYSQL_TYPE_VARCHAR

如果metadata小于256,则第一个字节表示数据的长度,如果metadata大于256

则前两个字节表示数据的长度。

时间: 2024-10-06 08:27:37

Mysql binlog 解析的相关文章

MySQL Binlog 解析工具 Maxwell 详解

maxwell 简介 Maxwell是一个能实时读取MySQL二进制日志binlog,并生成 JSON 格式的消息,作为生产者发送给 Kafka,Kinesis.RabbitMQ.Redis.Google Cloud Pub/Sub.文件或其它平台的应用程序.它的常见应用场景有ETL.维护缓存.收集表级别的dml指标.增量到搜索引擎.数据分区迁移.切库binlog回滚方案等.官网(http://maxwells-daemon.io).GitHub(https://github.com/zende

mysql binlog解析概要

1,dump协议: 根据数据库的ip+port创建socket,如果创建成功,说明链接建立成功,接下来是使用dump协议订阅binlog 链接建立成功之后,服务端会主动向客户端发送如下问候信息greeting(可以理解为经java转换后,是一个java对象), 在下面的代码中可以看到greeting中的信息: this.context.setServerStatus(greeting.getServerStatus());//this.context.setServerVersion(greet

MySQL Binlog解析(2)

一.TABLE_MAP_EVENT Used for row-based binary logging beginning with MySQL 5.1.5.The TABLE_MAP_EVENT defines the structure if the tables that are about to be changed. 用于从MySQL 5.1.5开始的基于行的二进制日志记录.每个ROW_EVENT之前都有一个TABLE_MAP_EVENT,用于描述表的内部ID和结构定义. 1)触发条件

原创工具binlog2sql:从MySQL binlog得到你要的SQL

binlog2sql是我开发的mysql binlog解析工具,它能帮助你从binlog得到你要的SQL.根据不同设置,你可以得到原始SQL.回滚SQL.去除主键的INSERT SQL等. 用途 数据回滚 主从切换后数据不一致的修复 从binlog生成标准SQL,带来的衍生功能 安装 $ git clone https://github.com/danfengcao/binlog2sql.git $ pip install -r requirements.txt 使用 MySQL server必

腾讯工程师带你深入解析 MySQL binlog

欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 本文由 腾讯云数据库内核团队 发布在云+社区 1.概述 binlog是Mysql sever层维护的一种二进制日志,与innodb引擎中的redo/undo log是完全不同的日志:其主要是用来记录对mysql数据更新或潜在发生更新的SQL语句,并以"事务"的形式保存在磁盘中: 作用主要有: 复制:MySQL Replication在Master端开启binlog,Master把它的二进制日志传递给slaves并回放来达到mast

解析MySQL binlog --(2)FORMAT_DESCRIPTION_EVENT

该格式描述事件时binlog version 4中为了取代之前版本的START_EVENT_3事件而引入的.是binlog文件的第一个事件,并在一个binlog文件中仅出现一次.具体定义:binlog-version:binlog版本mysql-server version:服务器版本create timestamp:指明binlog文件的创建时间.如果该binlog是由于切换产生,那么该字段是0event header length:189event type header lengths:记

20180705关于mysql binlog的解析方式

来自:https://blog.csdn.net/u012985132/article/details/74964366/ 关系型数据库和Hadoop生态的沟通越来越密集,时效要求也越来越高.本篇就来调研下实时抓取MySQL更新数据到HDFS. 本篇仅作为调研报告. 初步调研了canal(Ali)+kafka connect+kafka.maxwell(Zendesk)+kafka和mysql_streamer(Yelp)+kafka.这几个工具抓取MySQL的方式都是通过扫描binlog,模拟

MySQL——binlog

一.binlog简介: 1.什么是binlog: binlog日志用于记录所有更新了数据或者已经潜在更新了数据(例如,没有匹配任何行的一个DELETE)的所有语句.语句以"事件"的形式保存,它描述数据更改. 2.binlog的记录格式: Mysql binlog日志有三种格式,分别为:Statement ,MiXED ,和ROW: (在MySQL5.7.7版本之后,把binlog_format的默认值修改成了ROW.master将修改表的event写入binlog中,并且master将

PHP Client for Mysql Binlog

PHP解析Mysql Binlog,依赖于mysql-replication-listener库 详见:https://github.com/bullsoft/php-binlog Install MySQL Replication Listener https://github.com/bullsoft/mysql-replication-listener/archive/master.zip 该源代码,有一处bug,在 tcp_driver.cpp 第 650 行处: int Binlog_