[pymysqlbinlog] ROW_EVENT 从BINLOG中提取数据(SQL) & 从BINLOG中回滚数据(SQL)

导读

终于到了 row event的解析了. 只要解析了这部分, binlog基本上就算是解析完成了.

row event 记录了数据类型, 但是没得符号信息(5.7). 也没得字段信息(binlog_row_metadata=minimal). 所以可能无法拼接为SQL, 但可以转为BINLOG格式的语句. 格式参考如下: https://dev.mysql.com/doc/refman/8.0/en/binlog.html

BINLOG '
BASE64_57 (tablemap_event)
BASE64_57 (row_event)
'/*!*/;

BASE64_57 表示每57字节做一次base64 (测试发现仅仅是美观而已 -_-).

使用BINLOG语句的的时候 需要先声明FORMAT, 即先跑FORMAT_DESCRIPTION_EVENT的base64信息, 再跑后面的ROW_EVENT信息.

ROW EVENT

每个row event都要先有个tablemap event 来描述元数据信息. 每个row event 包含若干行数据,(无记录行数的字段, 每行之间都是连着放的, 所以要知道行数就必须全部信息解析出来… 离了个大谱).
数据存储的时候大端小端混着用, 主打一个恶心

对象大小(字节)描述
table_id6对应tablemap
flags2
extra分区表,NDB之类的信息的
widthpack_int字段数量
before_imageupdate or delete
after_imageupdate or insert
rownullbitmask_row * n

基本上都无固定大小, 读起来比较麻烦.

ROW 字段

大部分类型之前解析ibd文件的时候都解析过了, 这里就不重复说明了.
部分字段的某些信息需要读取tablemap的元数据信息. 基本上都是字段的长度, 比如 float(x)

字段类型元数据大小说明
tinyint/samllint/mediumint/int/bigint0小端, 符号取决于tablemap
decimal2见ibd2sql
float1float
double1double
time2/timestamp2/datetime21见ibd2sql
date0见ibd2sql
year0+1900
binary2(mdata >> 8) == 254
enum2(mdata >> 8) == 247
set2(mdata >> 8) == 248
char22字节大小
varchar/varbinary2varbinary也在这里, 转换SQL的时候就恼火了.
bit1int((mdata+7)/8)
json11字节记录 长度占用的字节数, 解析方式参考ibd2sql
BLOB/TEXT1同上
GEOMETRY1同上

“”“4:longblob/longtext”""
“”“3:mediumblob/mediumtext”""
“”“2:blob/text”""
“”“1:tinyblob/tinytext”""

数据存储就是这么个样子, 由于数据存储方式和ibd文件太像了. 对于大字段也没得分页, 所以解析起来还是很快的.
这里隐藏了很多细讲, 等后面工具发布的时候再自己去看吧.

测试

直接开始测试吧. 我们主要测试数据类型的支持和回滚能力 (正向解析的话 就官方的就够了.)

数据类型测试

测试出来和官方的是一样的.

普通数据类型

我们的工具解析出来如下. 我这里设置了binlog_row_metadata=full, 所以由字段名.
[pymysqlbinlog] ROW_EVENT 从BINLOG中提取数据(SQL) & 从BINLOG中回滚数据(SQL)-每日运维
官方的解析出来如下

大字段

[pymysqlbinlog] ROW_EVENT 从BINLOG中提取数据(SQL) & 从BINLOG中回滚数据(SQL)-每日运维

空间坐标

[pymysqlbinlog] ROW_EVENT 从BINLOG中提取数据(SQL) & 从BINLOG中回滚数据(SQL)-每日运维

数据回滚测试

数据正向解析用处不大, 主要还是看回滚, 为了方便验证, 这里就使用简单一点的表.
[pymysqlbinlog] ROW_EVENT 从BINLOG中提取数据(SQL) & 从BINLOG中回滚数据(SQL)-每日运维
[pymysqlbinlog] ROW_EVENT 从BINLOG中提取数据(SQL) & 从BINLOG中回滚数据(SQL)-每日运维
PS: 回滚SQL 也是能正常解析的(又回滚回去了. 注:这里还没有做事务级别的回滚.)

测试发现 是能正常回滚的.

其实到这里,binlog解析基本上就算完了,后面就是写剩余功能和接口了. 写好了再发.

能解析ibd和binlog之后, 数据恢复基本上没啥问题了. 更何况还有备份.