使用 repl_mysql 监控表数据变更

介绍

repl_mysql 在 replication 的基础上增加了更多的功能选项, 基于此可以仅关注指定选项的表的更新. 由于原理同 MySQL 的主从复制, replication 即通过伪造 slave 的方式接收 MySQL master 端的所有更新操作, 不同于真实的 slave, repl_mysql 不需要重新组织接收到的数据到 relay log 日志, 也不用重放 relay log 中的 sql.

注意事项

从上述的实现方式来看, 使用 repl_mysql 的时候需要注意以下几点:

1. 可以在一台主机中使用 repl_mysql 接收多个 MySQL master 的数据, 每个 master 对应一个独立的 repl_mysql 进程.
 不过需要注意连接的数量, 避免流量过大引起网络相关的问题;

2. MySQL binlog 为 ROW 格式的情况下会记录所有字段的变更, 单个请求的数据复制会较大, 在更新较多的场景中, 
repl_mysql 接收到的流量会较大, 使用 -rowevent 选项时输出的日志也会较多;

3. 过滤选项是在收到 master 所有数据之后建立的规则, 而不是指定哪个表就复制哪个表的数据. 这点同官方的 --replication-do-xx 
功能一致, 因为复制协议的局限性, slave 只能全部接收数据, 再在本地按照对应的规则更新数据;

4. 使用 repl_mysql 的过程中不影响 MySQL master 的数据, 仅增加网络传输 binlog 的开销;

5. 目前仅在 MySQL 5.5,5.6, 5.7 环境进行了测试, 未在 gtid 环境下测试. 如果程序运行过程中有异常或者崩溃, 
重启进程即可;

repl_mysql 支持的事件类型

repl_mysql 目前支持以下列表中的事件类型:

QUERY_EVENT
TABLE_MAP_EVENT
WRITE_ROWS_EVENTv0
UPDATE_ROWS_EVENTv0
DELETE_ROWS_EVENTv0
WRITE_ROWS_EVENTv1
UPDATE_ROWS_EVENTv1
DELETE_ROWS_EVENTv1
WRITE_ROWS_EVENTv2
UPDATE_ROWS_EVENTv2
DELETE_ROWS_EVENTv2

QUERY_TYPEbinlog_formatstatement 格式的时候所产生的数据更新语句, 其余为 binlog_formatrow 格式产生的数据类型. 如果需要增加更多类型, 可通过向源文件 repl_mysql.go 中的 map 变量 TypeCheck 增加更多的事件类型, 更多类型见: binlog-event

使用示例:

选项说明

repl_mysql 包含以下选项:

./repl_mysql -h
Usage of ./repl_mysql:
  -conf string                                                 # 配置文件名, 所有选项参数都可以写到配置文件中;
        configure file.
  -section string                                              # 配置文件中的 section 信息, 默认为 replication
        configure section. (default "replication") 
  -database string                                             # 如果指定数据库名, 则仅打印该数据库下表的更新信息;
        only replicate the database.
  -table string                                                # 如果指定表名, 则仅打印该表的更新信息, 和 database 配合使用则表示仅打印指定数据库的指定表的更新信息
        only replicate the table, multiple tables are separated by commas.
  -host string                                                 # master 的主机名;
        the mysql master server address. (default "localhost")
  -port int                                                    # master 的端口;
        the mysql master server port. (default 3306)
  -user string                                                 # 复制用户名
        replicate user (default "user_repl")
  -pass string                                                 # 复制用户的密码;
        replicate user password 
  -binlog string                                               # 需要复制的 master 的 binlog 文件名;
        replicate from this binlog file
  -pos int                                                     # 需要复制的 master 的 binlog 文件的位置;
        replicate from this position which in the binlog file
  -rowevent                                                    # 如果为 row 格式, 是否打印详细的更新信息;
        whether print row event change
  -serverid int                                                # 唯一的 server id 信息, 默认为 99999.
        unique server id in the replication (default 99999)

使用 repl_mysql 的时候, 必须使用 -user-pass 选项, 用户的权限同复制用户的权限, 仅需要 replication slave 即可. 如果使用的时候没有指定 -binlog-pos 选项, 则使用当前 master 最新的 binlog 位置进行主从复制. serverid 默认为 99999, 其值和 master 的 server_id 不同即可.

配置文件示例

下述配置指定 repl_mysql 从 10.0.21.5:3306 实例中的最新的位置开始复制, 仅输出 percona 数据库中的 tttt 表的更新信息:

[replication]
user = user_repl
pass = xxxxxxxx
host = 10.0.21.5
port = 3301
database = percona
table    = tri1

使用示例:

./repl_mysql -conf conn.conf -rowevent
......

Time: 2018-10-07T17:02:15
Type: TableMapEvent
Host: 10.0.21.5, Port: 3301
Schema: percona
Table: tri1
Binlog: mysql-bin.000035, Logpos: 3177, Eventsize: 53
== UpdateRowsEventV2 ==
  TableID: 143
  Flags: 1
  Column count: 2
  Values:
   +--
    0:10
    1:"arsterczxx"
   +--
    0:10
    1:"arsterczxxxxx"

仅输出指定数据库的更新信息

# ./repl_mysql -host 10.0.21.5 -user user_repl -pass xxxxxx -port 3301 -database percona -rowevent -binlog mysql-bin.000035 -pos 3687
......
......

Time: 2018-10-08T10:22:53
Type: QueryEvent
Host: 10.0.21.5, Port: 3301
Schema: percona
Binlog: mysql-bin.000035, Logpos: 3687, Eventsize: 75
Query: BEGIN


Time: 2018-10-08T10:22:53
Type: TableMapEvent
Host: 10.0.21.5, Port: 3301
Schema: percona
Table: test1
Binlog: mysql-bin.000035, Logpos: 3744, Eventsize: 57
== UpdateRowsEventV2 ==
  TableID: 197
  Flags: 1
  Column count: 4
  Values:
   +--
    0:5
    1:"flz1"
    2:201
    3:"2018-09-29 18:16:27"
   +--
    0:5
    1:"flz1"
    2:10301
    3:"2018-09-29 18:16:27"



Time: 2018-10-08T10:23:22
Type: QueryEvent
Host: 10.0.21.5, Port: 3301
Schema: percona
Binlog: mysql-bin.000035, Logpos: 3982, Eventsize: 85
Query: BEGIN


Time: 2018-10-08T10:23:22
Type: QueryEvent
Host: 10.0.21.5, Port: 3301
Schema: percona
Binlog: mysql-bin.000035, Logpos: 4109, Eventsize: 127
Query: update tri1 set name = "arstercz" where id = 10

仅输出指定数据库的指定表的更新信息

输出 percona 库中的 tri1 或 tri2 表的更新信息:

./repl_mysql -host 10.0.21.5 -user user_repl -pass xxxxxx -port 3301 -database percona -table tri1,tri2 -rowevent -binlog mysql-bin.000035 -pos 3687
......
......

Time: 2018-10-08T10:23:22
Type: QueryEvent
Host: 10.0.21.5, Port: 3301
Schema: percona
Table: tri1
Binlog: mysql-bin.000035, Logpos: 4109, Eventsize: 127
Query: update tri1 set name = "arstercz" where id = 10

仅输出指定表的更新信息

只要表名相同即可, 不限数据库名:

./repl_mysql -host 10.0.21.5 -user user_repl -pass xxxxxx -port 3301 -table tri1 -rowevent -binlog mysql-bin.000035 -pos 3687                  
......
......

Time: 2018-10-08T10:23:22
Type: QueryEvent
Host: 10.0.21.5, Port: 3301
Schema: percona
Table: tri1
Binlog: mysql-bin.000035, Logpos: 4109, Eventsize: 127
Query: update tri1 set name = "arstercz" where id = 10

Time: 2018-10-08T10:35:43
Type: QueryEvent
Host: 10.0.21.5, Port: 3301
Schema: percona2
Table: tri1
Binlog: mysql-bin.000035, Logpos: 4865, Eventsize: 129
Query: update tri1 set name = "arstercz" where id = 10