导读
终于到了 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_id | 6 | 对应tablemap |
flags | 2 | |
extra | 分区表,NDB之类的信息的 | |
width | pack_int | 字段数量 |
before_image | update or delete | |
after_image | update or insert | |
row | nullbitmask_row * n |
基本上都无固定大小, 读起来比较麻烦.
ROW 字段
大部分类型之前解析ibd文件的时候都解析过了, 这里就不重复说明了.
部分字段的某些信息需要读取tablemap的元数据信息. 基本上都是字段的长度, 比如 float(x)
字段类型 | 元数据大小 | 说明 |
---|---|---|
tinyint/samllint/mediumint/int/bigint | 0 | 小端, 符号取决于tablemap |
decimal | 2 | 见ibd2sql |
float | 1 | float |
double | 1 | double |
time2/timestamp2/datetime2 | 1 | 见ibd2sql |
date | 0 | 见ibd2sql |
year | 0 | +1900 |
binary | 2 | (mdata >> 8) == 254 |
enum | 2 | (mdata >> 8) == 247 |
set | 2 | (mdata >> 8) == 248 |
char | 2 | 2字节大小 |
varchar/varbinary | 2 | varbinary也在这里, 转换SQL的时候就恼火了. |
bit | 1 | int((mdata+7)/8) |
json | 1 | 1字节记录 长度占用的字节数, 解析方式参考ibd2sql |
BLOB/TEXT | 1 | 同上 |
GEOMETRY | 1 | 同上 |
“”“4:longblob/longtext”""
“”“3:mediumblob/mediumtext”""
“”“2:blob/text”""
“”“1:tinyblob/tinytext”""
数据存储就是这么个样子, 由于数据存储方式和ibd文件太像了. 对于大字段也没得分页, 所以解析起来还是很快的.
这里隐藏了很多细讲, 等后面工具发布的时候再自己去看吧.
测试
直接开始测试吧. 我们主要测试数据类型的支持和回滚能力 (正向解析的话 就官方的就够了.)
数据类型测试
测试出来和官方的是一样的.
普通数据类型
我们的工具解析出来如下. 我这里设置了binlog_row_metadata=full, 所以由字段名.
官方的解析出来如下
大字段
空间坐标
数据回滚测试
数据正向解析用处不大, 主要还是看回滚, 为了方便验证, 这里就使用简单一点的表.
PS: 回滚SQL 也是能正常解析的(又回滚回去了. 注:这里还没有做事务级别的回滚.)
测试发现 是能正常回滚的.
其实到这里,binlog解析基本上就算完了,后面就是写剩余功能和接口了. 写好了再发.
能解析ibd和binlog之后, 数据恢复基本上没啥问题了. 更何况还有备份.