解析MYSQL BINLOG 二进制格式(5)--WRITE_ROW_EVENT

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 原创:转载请说明出处谢谢! 上接 http://blog.itpub.net/7728585/viewspace-2133188/ 解析MYSQL BINLOG 二进制格式(1)--准备工作  http://blog.
原创:转载请说明出处谢谢!
上接
http://blog.itpub.net/7728585/viewspace-2133188/ 解析MYSQL BINLOG 二进制格式(1)--准备工作 
http://blog.itpub.net/7728585/viewspace-2133189/ 解析MYSQL BINLOG 二进制格式(2)--FORMAT_DESCRIPTION_EVENT 
http://blog.itpub.net/7728585/viewspace-2133321/ 解析MYSQL BINLOG 二进制格式(3)--QUERY_EVENT 
http://blog.itpub.net/7728585/viewspace-2133429/ 解析MYSQL BINLOG 二进制格式(4)--TABLE_MAP_EVENT 


class:Write_rows_log_event
event:WRITE_ROW_EVENT
event_code:30

自从5.1.18开始,row模式下的insert的event,为什么要叫write不叫insert
呢无赖...
这部分在internals文档中有点小的问题,我也是看了源码的描述才找到,
在文档中也写到[TODO:following needs verification;it's guesswork]
就是fixed data中有2 bytes的m_extra_row_data其值当前为
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
下面有部分源码截取。如果不知道这两个字节读取就会有问题。至少5.6,5.7都有的
老版本我也没有验证。


--fixed data  10字节(5.6,5.7中描述为 ROWS_HEADER_LEN_V2)
  6 bytes 表ID
  2 bytes 保留
  2 bytes 文档中并没有描述
  源码中描述为:
  uchar    *m_extra_row_data;   /* Pointer to extra row data if any */
                                /* If non null, first byte is length */
  源码中是这样写入的:
  if (likely(!log_bin_use_v1_row_events))
  {
    /*
       v2 event, with variable header portion.
       Determine length of variable header payload
    */
    uint16 vhlen= 2;
    uint16 vhpayloadlen= 0;
    uint16 extra_data_len= 0;
    if (m_extra_row_data)
    {
      extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
      vhpayloadlen= RW_V_TAG_LEN + extra_data_len;
    }


    /* Var-size header len includes len itself */
    int2store(buf + RW_VHLEN_OFFSET, vhlen + vhpayloadlen);
    rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V2);


    /* Write var-sized payload, if any */
    if ((vhpayloadlen > 0) &&
        (rc == 0))
    {
      /* Add tag and extra row info */
      uchar type_code= RW_V_EXTRAINFO_TAG;
      rc= wrapper_my_b_safe_write(file, &type_code, RW_V_TAG_LEN);
      if (rc==0)
        rc= wrapper_my_b_safe_write(file, m_extra_row_data, extra_data_len);
    }
  }
  else
  {
    rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V1);
  }


可以看到实际上写入的就是
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
有兴趣可以参考源码:
Rows_log_event::write_data_header(IO_CACHE *file)
                                
--variable data part
  packed integer:表中字段个数,这个地方为packed integer自行参考源码
                  uchar *net_store_length
  var-size:文档解释为每一位代表是否字段用到了 长度为INT((n+7)/8) n代表字段数量
           源码描述为 m_cols; /* Bitmap denoting columns available */
           测试表现这一字节和binlog_row_image设置有关,默认为FULL每一个字节始终为
           0XFF 
  var-size:每一位代表的字段的值是否为NULL,长度为INT((n+7)/8) n代表字段数量,
  他采用一个位图的方式。
           1:NULL
           0:NOT NULL
  var-size:这部分就是真正的数据了。
  


为了验证我做了如下的测试表:
mysql> create table testnull2 (id int,name1 varchar(20),name2 varchar(20));
Query OK, 0 rows affected (0.09 sec)


mysql> insert into testnull2 values(NULL,'test',NULL);
Query OK, 1 row affected (0.01 sec)


可以看到我只是插入的数据第一个字段第三个字段都是NULL,好我们看是解析,这次试用
mysqlbinlog 自带的--hexdump方式和自己开发的工具./infobin,这个工具就是通过自己
对binlog event的认知进行解析的,做这个工具的目的在于简化和友好的输出,方便我以后
的测试使用,同时也验证了我的全部说法,有时候mysqlbinlog的输出有点过于繁多,不便于
描述和测试,关于XID_EVENT和GTID_EVENT在后面描述
关于工具我放到了百度云盘
http://pan.baidu.com/s/1jHIWUN0

[root@testmy data]# ./infobin  test.000183
Check is Little_endian
Author: gaopeng QQ:22389860 Mail: gaopp_200217@163.com 
Waring: This tool only Little_endian platform!
Little_endian check ok!!!
-------------Now begin--------------
Check Mysql Version is:5.7.13-log
Check Mysql binlog format ver is:V4
------------Detail now--------------
>Gtid Event:Pos:194(0Xc2) N_pos:259(0X103) Time:1486946663 Event_size:65(bytes) 
Gtid:4a6f2a67-5d87-11e6-a6bd-0c29a879a3:1000448
-->Query Event:Pos:259(0X103) N_Pos:400(0X190) Time:1486946663 Event_size:141(bytes) 
Exe_time:0  Use_db:test Statment(35b-trun):create table testnull2 (id int,name
>Gtid Event:Pos:400(0X190) N_pos:465(0X1d1) Time:1486946680 Event_size:65(bytes) 
Gtid:4a6f2a67-5d87-11e6-a6bd-0c29a879a3:1000449
-->Query Event:Pos:465(0X1d1) N_Pos:537(0X219) Time:1486946680 Event_size:72(bytes) 
Exe_time:0  Use_db:test Statment(35b-trun):BEGIN
---->Map Event:Pos537(0X219) N_pos:595(0X253) Time:1486946680 Event_size:58(bytes) 
TABLE_ID:210 DB_NAME:test TABLE_NAME:testnull2
------>Insert Event:Pos:595(0X253) N_pos:636(0X27c) Time:1486946680 Event_size:41(bytes) 
Dml on table: test.testnull2  table_id:210 Gno:1000449 
>Xid Event:Pos:636(0X27c) N_Pos:667(0X29b) Time:1486946680 Event_size:31(bytes) 
COMMIT 1000449 /*!add by tool*/

这里找到了insert event:
------>Insert Event:Pos:595(0X253) N_pos:636(0X27c) Time:1486946680 Event_size:41(bytes) 
Dml on table: test.testnull2 Gno:1000449 
这里这个event的开始位置为595

进行使用mysqlbinlog --hexdump格式
# at 595
#170213  8:44:40 server id 93157  end_log_pos 636 CRC32 0x32dd470a 
# Position  Timestamp   Type   Master ID        Size      Master Pos    Flags 
#      253 78 01 a1 58   1e   e5 6b 01 00   29 00 00 00   7c 02 00 00   00 00
#      266 d2 00 00 00 00 00 01 00  02 00 03 ff fd 04 74 65 |..............te|
#      276 73 74 0a 47 dd 32                                |st.G.2|
#       Write_rows: table id 210 flags: STMT_END_F


下面是-vv的输出
### INSERT INTO `test`.`testnull2`
### SET
###   @1=NULL /* type=3 meta=0 nullable=1 is_null=1 */
###   @2='test' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
###   @3=NULL /* VARSTRING(60) meta=60 nullable=1 is_null=1 */

分解:
--event header 部分就不解析了table id 210,
  --hexdump也明确的解析了,不理解参考前面的文章
  # Position  Timestamp   Type   Master ID        Size      Master Pos    Flags 
  #      253 78 01 a1 58   1e   e5 6b 01 00   29 00 00 00   7c 02 00 00   00 00
--fixed data
d2 00 00 00 00 00:表ID就是./infobin中的TABLE_ID:210 也是mysqlbinlog中的Write_rows: table id 210
01 00:保留
02 00:m_extra_row_data,这部分是我看源码找到的。
--variable data part
03:表中字段个数,当然我建表就是3个字段
ff: 源码描述为 m_cols; /* Bitmap denoting columns available */    
fd: 11111101 代表字段@1=NULL和@3=NULL,但是字段@2不为空这和mysqlbinlog解析的一致
    @1=NULL /* type=3 meta=0 nullable=1 is_null=1 */
    @2='test' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
    @3=NULL /* VARSTRING(60) meta=60 nullable=1 is_null=1 */
04:var 长度04 就是数据'test'的长度为4,当然为4
74 65 73 74:字符串'test'
ca 3f c1 05:crc 32校验

到此为止WRITE_ROW_EVENT解析完毕
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
12天前
|
存储 SQL 关系型数据库
mysql 的ReLog和BinLog区别
MySQL中的重做日志和二进制日志是确保数据库稳定性和可靠性的关键组件。重做日志主要用于事务的持久性和原子性,通过记录数据页的物理修改信息来恢复未提交的事务;而二进制日志记录SQL语句的逻辑变化,支持数据复制、恢复和审计。两者在写入时机、存储方式及配置参数等方面存在显著差异。
|
3天前
|
存储 关系型数据库 MySQL
double ,FLOAT还是double(m,n)--深入解析MySQL数据库中双精度浮点数的使用
本文探讨了在MySQL中使用`float`和`double`时指定精度和刻度的影响。对于`float`,指定精度会影响存储大小:0-23位使用4字节单精度存储,24-53位使用8字节双精度存储。而对于`double`,指定精度和刻度对存储空间没有影响,但可以限制数值的输入范围,提高数据的规范性和业务意义。从性能角度看,`float`和`double`的区别不大,但在存储空间和数据输入方面,指定精度和刻度有助于优化和约束。
|
22小时前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
21 9
|
11天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
29天前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的binlog日志文件
MySQL的binlog日志记录了所有对数据库的更改操作(不包括SELECT和SHOW),主要用于主从复制和数据恢复。binlog有三种模式,可通过设置binlog_format参数选择。示例展示了如何启用binlog、设置格式、查看日志文件及记录的信息。
|
1月前
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
104 3
|
29天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
67 2
|
2月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
75 0
|
2月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
57 0
|
2月前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
65 0

推荐镜像

更多