MySQLbinlog日志03binlog日志字节码解析

本系列博客主要介绍MySQL数据库的binlog日志的相关内容,这个系列的主题包括:

MySQLbinlog日志01binlog日志基本操作

MySQLbinlog日志02binlog日志用于数据恢复

MySQLbinlog日志03binlog日志字节码解析

MySQLbinlog日志04binlog日志字节码解析之二Write_Rows事件

本博客主要内容包括:

binlog事件类型

binlog事件头部结构

binlog字节码分析的准备工作

binlog日志文件MAGIC代码

Format desc事件

Table map事件

下一篇博客

MySQLbinlog日志04binlog日志字节码解析之二Write_Rows事件

将介绍:

Write rows事件

1. binlog事件类型

MySQL Server 5.7.22支持的事件类型如下所示,总共定义了38种。

START_EVENT_V3= 1,

QUERY_EVENT= 2,

STOP_EVENT= 3,

ROTATE_EVENT= 4,

INTVAR_EVENT= 5,

LOAD_EVENT= 6,

SLAVE_EVENT= 7,

CREATE_FILE_EVENT= 8,

APPEND_BLOCK_EVENT= 9,

EXEC_LOAD_EVENT= 10,

DELETE_FILE_EVENT= 11,

NEW_LOAD_EVENT= 12,

RAND_EVENT= 13,

USER_VAR_EVENT= 14,

FORMAT_DESCRIPTION_EVENT= 15,

XID_EVENT= 16,

BEGIN_LOAD_QUERY_EVENT= 17,

EXECUTE_LOAD_QUERY_EVENT= 18,

TABLE_MAP_EVENT = 19,

PRE_GA_WRITE_ROWS_EVENT = 20,

PRE_GA_UPDATE_ROWS_EVENT = 21,

PRE_GA_DELETE_ROWS_EVENT = 22,

WRITE_ROWS_EVENT_V1 = 23,

UPDATE_ROWS_EVENT_V1 = 24,

DELETE_ROWS_EVENT_V1 = 25,

INCIDENT_EVENT= 26,

HEARTBEAT_LOG_EVENT= 27,

IGNORABLE_LOG_EVENT= 28,

ROWS_QUERY_LOG_EVENT= 29,

WRITE_ROWS_EVENT = 30,

UPDATE_ROWS_EVENT = 31,

DELETE_ROWS_EVENT = 32,

GTID_LOG_EVENT= 33,

ANONYMOUS_GTID_LOG_EVENT= 34,

PREVIOUS_GTIDS_LOG_EVENT= 35,

TRANSACTION_CONTEXT_EVENT= 36,

VIEW_CHANGE_EVENT= 37,

XA_PREPARE_LOG_EVENT= 38,

对于使用binlog日志文件进行数据恢复来说,下面4个事件非常重要:

TABLE_MAP_EVENT = 19,  将数据库名和表名和表id关联起来。

  WRITE_ROWS_EVENT = 30, INSERT语句使用。 

  UPDATE_ROWS_EVENT = 31,UPDATE语句使用。

  DELETE_ROWS_EVENT = 32,DELETE语句使用。

后面这三种事件处理方式非常类似,都是基于Rows_event,即包含记录行数据。

1. binlog事件头部结构

binlog事件具有相同的头部结构,总共19个字节。下表中偏移和长度均为十进制整数。


偏移


长度


字段


0


4


时间戳


4


1


事件类型


5


4


MySQL server-id


9


4


本事件的长度


13


4


下一个事件的开始位置


17


2


标志

上面表格中偏移量13长度4字节的字段,在<<MySQL Internals Manual>>(2006)文件中描述如下:

事件头部结构中的这个字段在MySQL Server 5.7.22源代码中的注释:

事件头部结构在MyFlash工具的源代码中定义如下(2019,适用于v4版本的binlog):

从后面的分析中可以看到,在MySQL Server 5.17..22版本产生的binlog日志文件中,认为是下一个事件的开始位置更为合适。这个字段的作用主要是用于在整个文件中快速的遍历各个事件从而找到特定的事件。

1. binlog字节码分析的准备工作

本文的目标是通过解析MySQL数据库的binlog日志文件的字节码来了解binlog日志文件的格式。

目标binlog文件:mysql_binlog.000003

为了分析方便,复制为all.binlog,通过hexdump程序取得十六进制格式的文本文件all.hex,通过mysqlbinlog程序取得对应的sql文件。

[[email protected] binlog]# ls -l all.*

-rw-r-----. 1 root root 10015 Sep 21 17:58 all.binlog

-rw-r--r--. 1 root root 49462 Sep 21 17:45 all.hex

-rw-r--r--. 1 root root 36776 Sep 21 17:43 all.sql

1. binlog日志文件MAGIC代码。

bin日志文件的magic代码的值在MySQL Server 5.7.22源代码中的定义如下:

binlog日志文件的前面4个字节是固定的magic代码,内容为“.bin”。

1. Format desc事件

每个binlog日志文件的第1个事件总是Format_desc。

mysql> show binlog events in ‘mysql_binlog.000003‘ limit 1\G

*************************** 1. row ***************************

Log_name: mysql_binlog.000003

Pos: 4

Event_type: Format_desc

Server_id: 101

End_log_pos: 123

Info: Server ver: 5.7.22-log, Binlog ver: 4

通过binlog文件的字节码可以分析第1个事件的内容。

下面通过分析第1个事件的事件头部结构。

时间戳:

mysql> select from_unixtime(0+0x5ba39a5c);

+-----------------------------+

| from_unixtime(0+0x5ba39a5c) |

+-----------------------------+

| 2018-09-20 21:02:20         |

+-----------------------------+

1 row in set (0.00 sec)

事件的字节数大小,以及事件的结束位置,以及下一个事件的开始位置:

mysql> select 0+0x77, 4+0x77 , 0+0x7b;

+--------+--------+--------+

| 0+0x77 | 4+0x77 | 0+0x7b |

+--------+--------+--------+

|    119 |    123 |    123 |

+--------+--------+--------+

1 row in set (0.00 sec)

因此,第1个事件的事件头部结构的各个字段的值如下:


字段


字节码



时间戳


5c9aa35b


2018-09-20 21:02:20


事件类型


0f


15


MySQL server-id


65000000


101


本事件的长度


77000000


119


下一个事件的开始位置


7b000000


123


标志


0000


0

这个事件的事件头信息与前面show binlog events 的结果是一致的。

show binlog events 的结果中pos是这个事件的事件头结构的开始位置,即在整个文件中的偏移量,第1个事件,因此偏移量总是4。 End_log_pos是这个事件的所有数据的最后一个字节之后的那个字节的位置,即下一个事件的事件头结构的开始位置。

这个事件的长度是119,这个长度包括事件头结构和事件具体内容两个部分。

现在需要了解Format Desc事件的内容部分的具体格式:

在MySQL Server 5.7.22版本的源代码中找到了以下的注释:

似乎显示binlog日志是v4版本的,但是其中的基类的名字似乎显示binlog日志是v3版本的。

看到下面这段注释终于明白了。MySQL Server V5.7.22的binlog日志是V4版本的,只是这个Format_desc 事件是从Start_event_v3派生而来的。

至此,Format Desc事件的具体内容的格式已经清楚了:

由于事件的头部结构的长度固定为19个字节,因此,此处的第1个字段的事件内部偏移为19。


事件偏移


长度


字段


19


2


binlog版本号


21


50


Server版本信息


71


4


创建时间戳


75


1


头部结构的长度


76


N

现在来观察这个Format Desc事件的具体内容部分。

具体内容部分的开始位置和结束位置如下所示:

mysql> select hex(4+19),hex(4+119-1);

+-----------+--------------+

| hex(4+19) | hex(4+119-1) |

+-----------+--------------+

| 17        | 7A           |

+-----------+--------------+

1 row in set (0.01 sec)

即下图中灰色部分所示区域。

计算时间戳的偏移量:

mysql> select hex(4+71);

+-----------+

| hex(4+71) |

+-----------+

| 4B        |

+-----------+

1 row in set (0.00 sec)

转换为human-readable时间:

mysql> select from_unixtime(0x5ba39a5c);

+---------------------------+

| from_unixtime(0x5ba39a5c) |

+---------------------------+

| 2018-09-20 21:02:20       |

+---------------------------+

1 row in set (0.00 sec)

前面介绍的事件头部结构(19个字节固定长度)对每个事件来说都是相同的结构相同的长度,称之为common Header。

binlog事件的事件相关头部的长度,事件相关头部即具体某个事件特有的结构,称之为Post Header。

事件类型的长度数组:

存储本MySQL Server支持的每一种事件的Post Header Length,即事件相关头部的长度。前面已经介绍过,总共38种类型的事件,因此这个数组总共更有38个元素,总共占用38个字节。

上图中灰色标记区域即是这个数组的内容。

由于Format Desc事件的事件类型是15,因此这个事件的Post Header Length是0x5f,即十进制的95。可以这样来验证:

mysql> select 2+50+4+1+38;

+-------------+

| 2+50+4+1+38 |

+-------------+

|          95 |

+-------------+

1 row in set (0.00 sec)

上述元素的各项即Format Desc 事件的事件相关头部的各个组成部分的长度。

因此,Format Desc事件的具体内容部分的各个字段的值总结如下:


字段


字节码



binlog版本号


0400


4


Server版本信息


352e372e32322d6c6f6700 .....


5.7.22-log


创建时间戳


5c9aa35b


2018-09-20 21:02:20


头部结构的长度


13


19


事件类型数组


省略


省略

前面已经了解这个事件的总长度是119个字节,刚刚介绍都是事件的头部:Common Header和Post Header,总共95个字节。 可以发现实际数据显示出多了5个字节:

mysql> select 19+95, 119-(19+95);

+-------+-------------+

| 19+95 | 119-(19+95) |

+-------+-------------+

|   114 |           5 |

+-------+-------------+

1 row in set (0.00 sec)

这5个字节的具体内容是什么,稍后介绍。

下面进一步了解一下多出来的5个字节的真正的内容是什么。

找到了以下这个代码片段:

在95个字节之后还写入了一个字节,这个字节用于指示是否使用校验码。这个字节的具体定义如下所示:

从前面的字节码截图可以看到,此处该值为1,即使用CRC32校验。 在这个write函数中并没有填充紧接着的4个字节,猜想有可能在其它地方处理了4个字节。

马上看到了这个代码片段:

其中定义了一个CRC32的签名长度,正好4个字节。因此多出来的4个字节有可能是CRC32签名的结果。

至此,Format Desc事件字节码分析完毕。

Write rows事件将在下一篇博客中介绍。

原文地址:https://www.cnblogs.com/coe2coe/p/9690685.html

时间: 2024-08-03 08:42:04

MySQLbinlog日志03binlog日志字节码解析的相关文章

MySQLbinlog日志04binlog日志字节码解析之二Write_Rows事件

本系列博客主要介绍MySQL数据库的binlog日志的相关内容,这个系列的主题包括: MySQLbinlog日志01binlog日志基本操作 MySQLbinlog日志02binlog日志用于数据恢复 MySQLbinlog日志03binlog日志字节码解析 MySQLbinlog日志04binlog日志字节码解析之二Write_Rows事件 前一篇博客介绍了 MySQLbinlog日志03binlog日志字节码解析 本篇博客将接着介绍Write Rows事件的字节码解析. 7.Write ro

Log4Qt快速入门——Log4Qt日志输出重定向源码解析

Log4Qt快速入门--Log4Qt日志输出重定向源码解析 一.Appender简介 1.Appender简介 Appender是所有Appender的抽象类,是对记录日志形式的抽象.Log4Qt(Qt4版本)中Appender继承体系如下: 2.Appender接口 virtual Filter *filter() const = 0; virtual QString name() const = 0; virtual Layout *layout() const = 0; virtual b

JAVA字节码解析

Java字节码指令 Java 字节码指令及javap 使用说明 ### java字节码指令列表 字节码 助记符 指令含义 0x00 nop 什么都不做 0x01 aconst_null 将null推送至栈顶 0x02 iconst_m1 将int型-1推送至栈顶 0x03 iconst_0 将int型0推送至栈顶 0x04 iconst_1 将int型1推送至栈顶 0x05 iconst_2 将int型2推送至栈顶 0x06 iconst_3 将int型3推送至栈顶 0x07 iconst_4

从字节码层面看“HelloWorld”

一.HelloWorld 字节码生成 众所周知,Java 程序是在 JVM 上运行的,不过 JVM 运行的其实不是 Java 语言本身,而是 Java 程序编译成的字节码文件.可能一开始 JVM 是为 Java 语言服务的,不过随着编译技术和 JVM 自身的不断发展和成熟,JVM 已经不仅仅只运行 Java 程序.任何能编译成为符合 JVM 字节码规范的语言都可以在 JVM 上运行,比较常见的 Scala.Groove.JRuby等.今天,我就从大家最熟悉的程序“HelloWorld”程序入手,

利用无效字节码指令引发逆向工具崩溃(一)

由于大部分逆向工具都是线性读取字节码并解析,当遇到无效字节码时,就会引起反编译工具字节码解析失败.  我们可以插入无效字节码到DEX文件,但要保证该无效字节码永远不会被执行(否则您的程序就会崩溃了!). 首先我们新建一个测试类.为了绕过Dalvik运行时代码验证,BadCode.java要保证不被调用.(否则运行app,会出现java.lang.verifyerror异常) 然后生成apk,用ida打开classes.dex.并找到BadCode类的aaa方法.选中的三行代码对应"System.

行为模式--字节码

理论要点 什么是字节码模式:将行为编码为虚拟机器上的指令,来赋予其数据的灵活性.从而让数据易于修改,易于加载,并与其他可执行部分相隔离. 要点 1,字节码模式:指令集定义了可执行的底层操作.一系列的指令被编码为字节序列. 虚拟机使用中间值堆栈依次执行这些指令. 通过组合指令,可以定义复杂的高层行为. 2,可以理解为项目中的转表工具,将excel中的数据转为二进制数据,并读取到工程中.还有如在项目中使用protobuf,json,xml等都是这么个思路. 3,字节码类似GOF的解释器模式,这两种方

JVM总结(五):JVM字节码执行引擎

JVM字节码执行引擎 运行时栈帧结构 局部变量表 操作数栈 动态连接 方法返回地址 附加信息 方法调用 解析 分派 –“重载”和“重写”的实现 静态分派 动态分派 单分派和多分派 JVM动态分派的实现 基于栈的字节码解释执行引擎 基于栈的指令集与基于寄存器的指令集 JVM字节码执行引擎 虚拟机是相对于“物理机”而言的,这两种机器都有代码执行能力,其区别主要是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而虚拟机的执行引擎是自己实现的.因此程序员可以自行制定指令集和执行引擎的

lua执行字节码的过程介绍

前面一篇文章中介绍了lua给下面代码生成最终的字节码的整个过程,这次我们来看看lua vm执行这些字节码的过程. 1 foo = "bar" 2 local a, b = "a", "b" 3 foo = a 生成的字节码如下所示: 之前lua是在luaY_parser函数(入口)中完成了lua脚本的解析生成字节码的整个过程的,在生成了main func(过程见“lua解析赋值类型代码的过程“)后luaY_parser会返回一个Proto结构体指

Java虚拟机--虚拟机字节码执行引擎

Java虚拟机--虚拟机字节码执行引擎 所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机栈的栈元素.每一个方法从调用开始到执行完成的过程,都对应一个栈帧在虚拟机栈中的入栈出栈过程. 由于虚拟机栈是线程私有的,所以每一个线程都有一个自己的虚拟机栈,而每个虚拟机栈都是由许多栈帧组成.每一个栈帧都包括 局部变量表 操作数栈 动态连接 方法返回地址 额外附加信息 处于