mysql binlog解析

2023-09-03 13:02:06 浏览数 (2)

1 打开binlog

打开db管理工具,或者登陆mysql服务器:mysql -h127.0.0.1 -P3306 -uroot -p1008611

查看binlog是否打开:show variables like 'log_%';

ON即为打开了ON即为打开了

如果是OFF,则需要打开binlog:vi /etc/my.cnf

在[mysqld]下面增加: log-bin=mysql-bin binlog-format=ROW server_id=1

重启mysql: service mysqld restart

2 如何查看binlog

【如果只是了解,不要找最大id的log,可能正在写入中或者主从同步中,不要影响了线上操作】

代码语言:javascript复制
/usr/local/mysql/bin/mysqlbinlog -v --start-datetime="2023-09-02 00:00:00" --stop-datetime="2023-09-02 23:59:59" /usr/local/mysql/data/mysql-bin.000001

3 binlog格式

【下面的方法都是ROW格式的方法。Statement格式的,需要验证一下。不过,如果需要的是数据清洗等,则需要ROW,因为要获取到具体的数据;如果是主从同步等,则任意格式都可。】

3.1 insert

代码语言:javascript复制
# at 886746
#230902 17:53:37 server id 1  end_log_pos 886811 CRC32 0xa4b56817       Anonymous_GTID  last_committed=80       sequence_number=81      rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 886811
#230902 17:53:37 server id 1  end_log_pos 886891 CRC32 0x1513701c       Query   thread_id=3086  exec_time=0     error_code=0
SET TIMESTAMP=1693648417/*!*/;
BEGIN
/*!*/;
# at 886891
#230902 17:53:37 server id 1  end_log_pos 886989 CRC32 0xda1bb052       Table_map: `fatp`.`t_dw_conf_pipeline_template` mapped to number 244
# at 886989
#230902 17:53:37 server id 1  end_log_pos 887063 CRC32 0xc69ea049       Write_rows: table id 244 flags: STMT_END_F

BINLOG '
IQbzZBMBAAABGZhdHAAG3RfZHdfY29uZl9waXBlbGluZV90ZW1w
bGF0ZQAQCAMPDAAAAAEAAgAQ//9C/QIAAAAAAAAAA2treAswIDAgMSAqICog
PwGZsQUdZZmxBR1lAEmgnsY=
'/*!*/;
### INSERT INTO `fatp`.`t_dw_conf_pipeline_template`
### SET
###   @1=2
###   @2=NULL
###   @3='kkx'
###   @4='0 0 1 * * ?'
###   @5=1
###   @6='2023-09-02 17:53:37'
###   @7=NULL
###   @8='2023-09-02 17:53:37'
###   @9=NULL
###   @10=0
###   @11=NULL
###   @12=NULL
###   @13=NULL
###   @14=NULL
###   @15=NULL
###   @16=NULL
# at 887063
#230902 17:53:37 server id 1  end_log_pos 887094 CRC32 0x5eb043a3       Xid = 22402
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

大概描述一下这里的数据结构:

# at 886746代表本次Event log开始的地址。

#230902 17:53:37Event开始的时间。

server id 1本实例的id。一台服务器上可以部署多个实例,此值为my.conf文件中配置的server_id值。

end_log_pos 886811本条Event结束的地址。也就是下一个Event开始的地址。

CRC32 0xa4b56817循环冗余校验码。一种hash函数,redis集群模式下,判断key属于哪个slot的时候用的CRC64。

Anonymous_GTID在MySQL复制中,每个事务都会被分配一个唯一的GTID,以便在主服务器上生成的事务可以被从服务器正确地复制和应用。然而,有时会出现一些特殊情况,例如在从服务器上执行的本地事务或在主服务器上执行的未命名事务。这些事务没有明确的标识符,因此被称为"Anonymous_GTID"。GTID(Global Transaction Identifier)是MySQL中用于全局事务标识的机制,用于确保在复制环境中的数据一致性和可靠性。

last_committed=80上次commit的id。通常用于描述数据库事务的状态。它表示在一个数据库事务中,最后一个已经被提交(committed)的操作或语句。在数据库中,事务是一组相关的操作,这些操作要么全部成功执行并提交,要么全部回滚(撤销)。当事务中的所有操作都成功执行并提交时,可以说事务已经被"last_committed",也就是最后一个操作已经被提交。

sequence_number=81本次commit的id。一次事务包含多个操作或者Event,比如上面的都包含了4个Event,它们是同一个事务。如果有多条插入的话,事件只会更多。

rbr_only=yes是MySQL中的一个配置选项,用于启用基于行的复制(Row-Based Replication,RBR)模式。RBR是MySQL复制的一种模式,它以行为单位复制数据更改操作。在MySQL复制中,有三种复制模式可供选择:语句复制(Statement-Based Replication,SBR)、混合复制(Mixed-Based Replication,MBR)和基于行的复制(Row-Based Replication,RBR)。

SET @@SESSION.GTID_NEXT='ANONYMOUS'用于设置当前会话的下一个GTID(全局事务标识)值为'ANONYMOUS'。GTID是MySQL用于在复制环境中唯一标识事务的一种机制。每个事务都会被分配一个唯一的GTID,以便在主服务器上生成的事务可以被从服务器正确地复制和应用。'ANONYMOUS'在这里是一个示例值,可以根据需要设置不同的GTID值,开心就好。

Query:在MySQL复制中,Query Event是指在主服务器上执行的SQL查询语句所生成的二进制日志Event。当启用二进制日志(binary logging)时,MySQL会将主服务器上执行的每个SQL查询语句记录到二进制日志中,以便在复制过程中将这些查询语句传递给从服务器。在DDL的alter操作中,Query会将操作的语句一起携带;DML不会,因为有更详细的Event可以携带。

thread_id=3086本次操作的线程id。

SETTIMESTAMP=1693648417当前的时间戳。

BEGIN、COMMIT开启和提交一个事物,这中间就是一个事务的具体内容。

Table_map:`fatp`.`t_dw_conf_pipeline_template` mapped to number 244table_map事件,携带了database,table名称,并且设置了一个map值为244,后续操作直接用244,不用database,table参数。

Write_rows:table id 244:写入一行,在244表。并不是只有这个一个Flag表示写入一条数据,不同的版本有不同的Flag,详见附录判断写入Event的逻辑。

flags: STMT_END_F表示该事件结束了。此标志出现意味着Event完成。

BINLOG 一连串的十六进制这些数据代表了在主服务器上执行的数据库更改操作。具体来说,BINLOG记录包含了一系列的事件,每个Event都以特定的格式和结构进行编码,并以十六进制的形式进行记录。这些Event可以是查询事件、插入事件、更新事件、删除事件等,用于记录对数据库的各种操作。每个BINLOG Event都有其特定的格式和字段,用于描述和记录相应的数据库更改操作。这些字段包括事件类型、时间戳、数据库名称、表名称、受影响的行数、修改前后的数据值等。可以认为就是本例子中,非# 和 /*开头的内容。

INSERT INTO ****sql逻辑内容。但是里面可以看到,是从table的第一列开始,按照列index进行赋值的。并无具体的字段信息。如果要字段信息的话,需要通过其他的sql逻辑获取。

Xid =22402本次事务id。

自此,一个事务结束。

后续两个属性为文件的结尾,文件有更新则在这之间添加。

SET @@SESSION.GTID_NEXT='AUTOMATIC'GTID_NEXT是一个系统变量,用于指定下一个要执行的事务的GTID值。当将GTID_NEXT设置为 'AUTOMATIC' 时,MySQL会自动为当前会话生成下一个要执行的事务的GTID值。这意味着MySQL会根据复制配置和规则自动分配一个适当的GTID值。

DELIMITER ;用于指定SQL语句分隔符的关键字。在MySQL中,分号(;)通常用作SQL语句的结束符号。然而,在某些情况下,SQL语句本身可能包含分号,这会导致解析器错误地将其视为语句的结束。为了解决这个问题,可以用"DELIMITER"关键字来指定一个自定义的分隔符,以替代默认的分号。这样,解析器就会将自定义的分隔符作为语句的结束符号,而不是使用默认的分号。

【这里比较关键的一个点是,这是一个事务,包含了多个Event,依赖end_log_pos关键字关联,它们是一个整体。】

3.2 update

代码语言:javascript复制
# at 880434
#230902 16:23:42 server id 1  end_log_pos 880499 CRC32 0x1e28aa99       Anonymous_GTID  last_committed=56       sequence_number=57      rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 880499
#230902 16:23:42 server id 1  end_log_pos 880579 CRC32 0x566d2adb       Query   thread_id=3086  exec_time=0     error_code=0
SET TIMESTAMP=1693643022/*!*/;
BEGIN
/*!*/;
# at 880579
#230902 16:23:42 server id 1  end_log_pos 880677 CRC32 0xaa538350       Table_map: `fatp`.`t_dw_conf_pipeline_template` mapped to number 217
# at 880677
#230902 16:23:42 server id 1  end_log_pos 880819 CRC32 0x85e40231       Update_rows: table id 217 flags: STMT_END_F

BINLOG '
DvHyZBMBAAAAYgAAACVwDQHdfY29uZl9waXBlbGluZV90ZW1w
bGF0ZQARCA8PAwMDwEKwADAAADAAADAAPz/AVCDU6o=
DvHyZB8BAAAAjgAAALNwDR//////// Af AQAAAAAAAAAFVGVzdEELMCAw
IDEgKiAqID8CmbDtgA Af AQAAAAAAAAAFVGVzdEELMCAwIDEgKiAq
ID8DmbDtCwcEaQLkhQ==
'/*!*/;
### UPDATE `fatp`.`t_dw_conf_pipeline_template`
### WHERE
###   @1=1
###   @2='TestA'
###   @3='0 0 1 * * ?'
###   @4=NULL
###   @5=NULL
###   @6=NULL
###   @7=NULL
###   @8=NULL
###   @9=NULL
###   @10=NULL
###   @11=NULL
###   @12=2
###   @13='2023-08-22 16:44:07'
###   @14='hanx'
###   @15='2023-09-02 16:16:54'
###   @16='hanx'
###   @17=0
### SET
###   @1=1
###   @2='TestA'
###   @3='0 0 1 * * ?'
###   @4=NULL
###   @5=NULL
###   @6=NULL
###   @7=NULL
###   @8=NULL
###   @9=NULL
###   @10=NULL
###   @11=NULL
###   @12=3
###   @13='2023-08-22 16:44:07'
###   @14='hanx'
###   @15='2023-09-02 16:23:42'
###   @16='hanx'
###   @17=0
# at 880819
#230902 16:23:42 server id 1  end_log_pos 880850 CRC32 0xe8520873       Xid = 21270
COMMIT/*!*/;

Update_rows更改字段的事件。不同的版本有不同的Flag,详见附录判断更新事件的逻辑。

这里的BINLOG中,可以看到WHERE查询条件即为原始数据,SET即为更新后的数据。

3.3 delete

代码语言:javascript复制
# at 886362
#230902 17:46:05 server id 1  end_log_pos 886393 CRC32 0x71b5c8ad       Xid = 22292
COMMIT/*!*/;
# at 886393
#230902 17:51:23 server id 1  end_log_pos 886458 CRC32 0xc95544bc       Anonymous_GTID  last_committed=79       sequence_number=80      rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 886458
#230902 17:51:23 server id 1  end_log_pos 886530 CRC32 0x17f6e7cd       Query   thread_id=3086  exec_time=0     error_code=0
SET TIMESTAMP=1693648283/*!*/;
BEGIN
/*!*/;
# at 886530
#230902 17:51:23 server id 1  end_log_pos 886628 CRC32 0x4009b5b7       Table_map: `fatp`.`t_dw_conf_pipeline_template` mapped to number 244
# at 886628
#230902 17:51:23 server id 1  end_log_pos 886715 CRC32 0x9958ada2       Delete_rows: table id 244 flags: STMT_END_F

BINLOG '
mwXzZBMBAG3RfZHdfY29uZl9waXBlbGluZV90ZW1w
bGF0ZQAQAwMDAwzAAMAAAMAAAMAAwAD6/7e1CUA=
mwXzZCABAAAAVwAAAAAAABVRlc3RiCzAgMCAxICog
KiA/AZmxAugqBGVoYW54agCirViZ
'/*!*/;
### DELETE FROM `fatp`.`t_dw_conf_pipeline_template`
### WHERE
###   @1=2
###   @2=NULL
###   @3='Testb'
###   @4='0 0 1 * * ?'
###   @5=1
###   @6='2023-09-01 14:32:42'
###   @7='janx'
###   @8='2023-09-01 14:59:26'
###   @9='hanxj'
###   @10=0
###   @11=NULL
###   @12=NULL
###   @13=NULL
###   @14=NULL
###   @15=NULL
###   @16=NULL
# at 886715
#230902 17:51:23 server id 1  end_log_pos 886746 CRC32 0x9ee41972       Xid = 22401
COMMIT/*!*/;

Delete_rows删除rows的事件。不同的版本有不同的Flag,详见附录判断删除事件的逻辑。

这里的WHERE即为原始数据。

3.4 alter

代码语言:javascript复制
# at 880850
#230902 16:31:26 server id 1  end_log_pos 880915 CRC32 0x4cf1c038       Anonymous_GTID  last_committed=57       sequence_number=58      rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 880915
#230902 16:31:26 server id 1  end_log_pos 881063 CRC32 0x3b282d30       Query   thread_id=3086  exec_time=0     error_code=0
SET TIMESTAMP=1693643486/*!*/;
alter table t_dw_conf_pipeline_template add column f_a varchar(64)
/*!*/;

Query并且携带了alter语句:alter事件。这个比较特别,没有具体的Event类型来判断,需要结合逻辑。

如果有其他可以判断的方式,还请麻烦联系作者进行补充。

3.4.1 binlog格式

这里补充一个点,binlog有三种格式:ROW、STATEMENT、MIX。

ROW:记录每一行的数据的具体变化。有个不好的地方是,所有的变化的数据都记录了,有的数据后续删除了,但是前面的记录还在,导致binlog很多无效的数据,file利用率不高。

STATEMENT:记录每一个导致数据变化的sql,这样减少了数据的备份。但是会导致复制的主从不一致,比如主从版本不一致导致函数不一致,从而导致两方的值不一致,比如now()函数,还和机器的时间有关系。

MIX:混合两者。

ROW格式在新版本中进行了优化,对于数据变化的操作,记录了数据的具体变化。而对于表结构的变化使用了STATEMENT的形式,只记录sql语句,所以上面的alter binlog只有一条简单的sql,的确是省了很多空间。

Redis的RDB是创建所有的数据备份,适合初始化;AOF是append新数据,并会重写去掉无用的数据,比如过期的、delete的,适合增量同步,减少带宽占用。和binlog是不同的模式,不要搞混了。

3.5 注意

从上可以看出,一个事务包含了多个Event并按照顺序存储在binlog中,是一个整体。

如果要处理binlog,则需要按照顺序处理Event。具体的Delete_rows/Update_rows/Write_rows并不会有db、table的信息,需要从前一个的Table_map事件获取。并根据事件类型做相应的处理。

所以这个binlog文件,只能按照顺序读取事件,获得的事务内容可以并发处理,如数仓的ETL等。

4 谁干的!

有时候,数据库的记录被更改了,不知道谁或者哪个逻辑改的,需要找到具体操作者。

从binlog中可以找到操作更改的事务,在这个事务中找到Query事件,Query事件有个字段为thread_id,从而可以找到本次操作的线程id。

拿着这个线程id,在information_schema.processlist中可以找到属于哪个client ip,从而可以找到是哪个服务、客户端操作了这个事务导致语句被变更了。

代码语言:javascript复制
select*from information_schema.processlist where Id=64

【不清楚这个线程是不是一直存在,最好是及时处理。】

5 附录,事件类型

CRC32循环冗余校验码之后的一列是事件类型,具体内容如下:

代码语言:javascript复制
来自:https://github.com/osheroff/mysql-binlog-connector-java/blob/master/src/main/java/com/github/shyiko/mysql/binlog/event/EventType.java
这是一个很好的binlog监听和处理组件
/*
 * Copyright 2013 Stanley Shyiko
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.shyiko.mysql.binlog.event;

import java.util.stream.Stream;

/**
 * @author <a href="mailto:stanley.shyiko@gmail.com">Stanley Shyiko</a>
 * @see <a href="https://dev.mysql.com/doc/internals/en/event-meanings.html">Event Meanings</a> for the original
 * documentation.
 */
public enum EventType {

    /**
     * Events of this event type should never occur. Not written to a binary log.
     */
    UNKNOWN(0),
    /**
     * A descriptor event that is written to the beginning of the each binary log file. (In MySQL 4.0 and 4.1,
     * this event is written only to the first binary log file that the server creates after startup.) This event is
     * used in MySQL 3.23 through 4.1 and superseded in MySQL 5.0 by {@link #FORMAT_DESCRIPTION}.
     */
    START_V3(1),
    /**
     * Written when an updating statement is done.
     */
    QUERY(2),
    /**
     * Written when mysqld stops.
     */
    STOP(3),
    /**
     * Written when mysqld switches to a new binary log file. This occurs when someone issues a FLUSH LOGS statement or
     * the current binary log file becomes larger than max_binlog_size.
     */
    ROTATE(4),
    /**
     * Written every time a statement uses an AUTO_INCREMENT column or the LAST_INSERT_ID() function; precedes other
     * events for the statement. This is written only before a {@link #QUERY} and is not used in case of RBR.
     */
    INTVAR(5),
    /**
     * Used for LOAD DATA INFILE statements in MySQL 3.23.
     */
    LOAD(6),
    /**
     * Not used.
     */
    SLAVE(7),
    /**
     * Used for LOAD DATA INFILE statements in MySQL 4.0 and 4.1.
     */
    CREATE_FILE(8),
    /**
     * Used for LOAD DATA INFILE statements as of MySQL 4.0.
     */
    APPEND_BLOCK(9),
    /**
     * Used for LOAD DATA INFILE statements in 4.0 and 4.1.
     */
    EXEC_LOAD(10),
    /**
     * Used for LOAD DATA INFILE statements as of MySQL 4.0.
     */
    DELETE_FILE(11),
    /**
     * Used for LOAD DATA INFILE statements in MySQL 4.0 and 4.1.
     */
    NEW_LOAD(12),
    /**
     * Written every time a statement uses the RAND() function; precedes other events for the statement. Indicates the
     * seed values to use for generating a random number with RAND() in the next statement. This is written only
     * before a {@link #QUERY} and is not used in case of RBR.
     */
    RAND(13),
    /**
     * Written every time a statement uses a user variable; precedes other events for the statement. Indicates the
     * value to use for the user variable in the next statement. This is written only before a {@link #QUERY} and
     * is not used in case of RBR.
     */
    USER_VAR(14),
    /**
     * A descriptor event that is written to the beginning of the each binary log file.
     * This event is used as of MySQL 5.0; it supersedes {@link #START_V3}.
     */
    FORMAT_DESCRIPTION(15),
    /**
     * Generated for a commit of a transaction that modifies one or more tables of an XA-capable storage engine.
     * Normal transactions are implemented by sending a {@link #QUERY} containing a BEGIN statement and a {@link #QUERY}
     * containing a COMMIT statement (or a ROLLBACK statement if the transaction is rolled back).
     */
    XID(16),
    /**
     * Used for LOAD DATA INFILE statements as of MySQL 5.0.
     */
    BEGIN_LOAD_QUERY(17),
    /**
     * Used for LOAD DATA INFILE statements as of MySQL 5.0.
     */
    EXECUTE_LOAD_QUERY(18),
    /**
     * This event precedes each row operation event. It maps a table definition to a number, where the table definition
     * consists of database and table names and column definitions. The purpose of this event is to enable replication
     * when a table has different definitions on the master and slave. Row operation events that belong to the same
     * transaction may be grouped into sequences, in which case each such sequence of events begins with a sequence
     * of TABLE_MAP events: one per table used by events in the sequence.
     * Used in case of RBR.
     */
    TABLE_MAP(19),
    /**
     * Describes inserted rows (within a single table).
     * Used in case of RBR (5.1.0 - 5.1.15).
     */
    PRE_GA_WRITE_ROWS(20),
    /**
     * Describes updated rows (within a single table).
     * Used in case of RBR (5.1.0 - 5.1.15).
     */
    PRE_GA_UPDATE_ROWS(21),
    /**
     * Describes deleted rows (within a single table).
     * Used in case of RBR (5.1.0 - 5.1.15).
     */
    PRE_GA_DELETE_ROWS(22),
    /**
     * Describes inserted rows (within a single table).
     * Used in case of RBR (5.1.16 - mysql-trunk).
     */
    WRITE_ROWS(23),
    /**
     * Describes updated rows (within a single table).
     * Used in case of RBR (5.1.16 - mysql-trunk).
     */
    UPDATE_ROWS(24),
    /**
     * Describes deleted rows (within a single table).
     * Used in case of RBR (5.1.16 - mysql-trunk).
     */
    DELETE_ROWS(25),
    /**
     * Used to log an out of the ordinary event that occurred on the master. It notifies the slave that something
     * happened on the master that might cause data to be in an inconsistent state.
     */
    INCIDENT(26),
    /**
     * Sent by a master to a slave to let the slave know that the master is still alive. Not written to a binary log.
     */
    HEARTBEAT(27),
    /**
     * In some situations, it is necessary to send over ignorable data to the slave: data that a slave can handle in
     * case there is code for handling it, but which can be ignored if it is not recognized.
     */
    IGNORABLE(28),
    /**
     * Introduced to record the original query for rows events in RBR.
     */
    ROWS_QUERY(29),
    /**
     * Describes inserted rows (within a single table).
     * Used in case of RBR (5.1.18 ).
     */
    EXT_WRITE_ROWS(30),
    /**
     * Describes updated rows (within a single table).
     * Used in case of RBR (5.1.18 ).
     */
    EXT_UPDATE_ROWS(31),
    /**
     * Describes deleted rows (within a single table).
     * Used in case of RBR (5.1.18 ).
     */
    EXT_DELETE_ROWS(32),
    /**
     * Global Transaction Identifier.
     */
    GTID(33),
    ANONYMOUS_GTID(34),
    PREVIOUS_GTIDS(35),
    TRANSACTION_CONTEXT(36),
    VIEW_CHANGE(37),
    /**
     * Prepared XA transaction terminal event similar to XID except that it is specific to XA transaction.
     */
    XA_PREPARE(38),

    /**
     Extension of UPDATE_ROWS_EVENT, allowing partial values according
     to binlog_row_value_options.
     */
    PARTIAL_UPDATE_ROWS_EVENT(39),

    /**
     * Generated when 'binlog_transaction_compression' is set to 'ON'.
     * It encapsulates all the events of a transaction in a Zstd compressed payload.
     */
    TRANSACTION_PAYLOAD(40),

    /**
     * MariaDB Support Events
     *
     * @see <a href="https://mariadb.com/kb/en/replication-protocol/">Replication Protocol</a> for the original doc.
     */
    ANNOTATE_ROWS(160), //
    BINLOG_CHECKPOINT(161),
    MARIADB_GTID(162),
    MARIADB_GTID_LIST(163);

    private static final EventType[] TYPE_BY_EVENT_NUMBER = buildEventTypeIndex();
    private final int eventNumber;

    EventType(int eventNumber) {
        this.eventNumber = eventNumber;
    }

    private static EventType[] buildEventTypeIndex() {
        EventType[] types = EventType.values();
        int maxEventNumber = Stream.of(types).mapToInt(t -> t.eventNumber).max().orElse(-1);
        EventType[] index = new EventType[maxEventNumber 1];
        for (EventType type : types) {
            index[type.eventNumber] = type;
        }
        return index;
    }

    public static boolean isRowMutation(EventType eventType) {
        return EventType.isWrite(eventType) ||
            EventType.isUpdate(eventType) ||
            EventType.isDelete(eventType);
    }

    public static boolean isWrite(EventType eventType) {
        return eventType == PRE_GA_WRITE_ROWS ||
            eventType == WRITE_ROWS ||
            eventType == EXT_WRITE_ROWS;
    }

    public static boolean isUpdate(EventType eventType) {
        return eventType == PRE_GA_UPDATE_ROWS ||
            eventType == UPDATE_ROWS ||
            eventType == EXT_UPDATE_ROWS;
    }

    public static boolean isDelete(EventType eventType) {
        return eventType == PRE_GA_DELETE_ROWS ||
            eventType == DELETE_ROWS ||
            eventType == EXT_DELETE_ROWS;
    }

    public static EventType byEventNumber(int num) {
        return num >= 0 && num < TYPE_BY_EVENT_NUMBER.length ? TYPE_BY_EVENT_NUMBER[num] : null;
    }
}

这里的事件都会传递给使用端,可以在借助这个模块进行binlog监听并做定制化处理。

0 人点赞