- 尽可能在从库解析,避免对主库造成影响
- 先粗略定位涉及相关的库表操作的 binlog,再单独解析对应的 binlog 中的数据
- 在解析 DDL 时无需加 -v 输出详细信息(加快解析速度)
- 如果开启了 binlog_rows_query_log_events 参数,需要用 -vv 参数才可显示具体的 SQL 语句
如果只是解析出来查看,可以加 --base64-output=decode-rows 不显示行格式的内容:
mysqlbinlog --no-defaults -vv --base64-output=decode-rows mysql-bin.0000082. 解析指定 GTID 的事务
用来分析某个事务做了什么:
mysqlbinlog --no-defaults -vv --base64-output=decode-rows --include-gtids='00008027-0000-0000-0000-000000008027:234932' mysql-bin.0000083. 解析指定范围的 binlog a. 时间范围
–start-datetime、–stop-datetime 解析出指定时间范围内的 binlog,这个只适合粗略的解析,不精准,因此不要用来回放 binlog。有个小技巧:如果只能确定大概的时间范围,而且不确定在哪个 binlog 中,可以直接解析多个 binlog。比如大概在 15:20-16:20 内做了个表删除操作,但这个时间内有多个 binlog,可以这样:
mysqlbinlog --no-defaults -vv --base64-output=decode-rows --start-datetime='2022-04-11 15:20:00' --stop-datetime='2022-04-11 16:20:00' mysql-bin.000007 mysql-bin.000008b. 偏移范围
–start-position、–stop-position 解析 binlog 指定偏移量范围内的 binlog。如果同时指定了 --start-position 和 --stop-position,并且是解析多个 binlog,则 --start-position 只对第一个 binlog 生效,–stop-position 只对最后一个 binlog 生效。
这个常用场景是:已经解析过一次 binlog 并取得目标事务的 起始 position 后,精确的解析这一段 binlog:
mysqlbinlog --no-defaults -vv --base64-output=decode-rows --start-position='1700' --stop-position='2049' mysql-bin.000008 # at 1700 --"start-position是 GTID event 前的这个 position" ... ... SET @@SESSION.GTID_NEXT= '00008027-0000-0000-0000-000000008027:234933'; # at 1779 #220411 16:34:34 server id 8027 end_log_pos 1854 CRC32 0x8045a89d Query thread_id=10 exec_time=0 error_code=0 SET TIMESTAMP=1649666074; BEGIN ; # at 1854 #220411 16:34:34 server id 8027 end_log_pos 1909 CRC32 0x95943ed8 Rows_query # delete from zhouwb where id = 6 # at 1909 #220411 16:34:34 server id 8027 end_log_pos 1969 CRC32 0xbc91d326 Table_map: `test`.`zhouwb` mapped to number 88 # at 1969 #220411 16:34:34 server id 8027 end_log_pos 2018 CRC32 0x55ee80ec Delete_rows: table id 88 flags: STMT_END_F ### DELETE FROM `test`.`zhouwb` ### WHERe ### @1=6 ### @2='nanchang' # at 2018 #220411 16:34:34 server id 8027 end_log_pos 2049 CRC32 0x0e1be5af Xid = 21 COMMIT; # at 2049 --"stop-position是 COMMIT event 后的这个 position"c. GTID范围
–include-gtids、–exclude-gtids 详细看参数解释。
4 回放 binlog- 回放一定不能加 --base64-output=decode-rows 参数,因为不会解析出行格式(这是binlog真正有效的部分);
- 回放也可以用上面指定范围的参数;
- 解析 binlog 回放到本实例,不需要修改 server id,但要注意 GTID 是否已存在;
- GTID 已经存在,回放不会报错,但也不会真正回放这些事务,可以通过 --skip-gtids 参数跳过 GTID 的限制;
mysqlbinlog --no-defaults --skip-gtids mysql-bin.000008 | mysql -uroot -p -S /tmp/mysql_sandbox8027.sock参数解释 1. --no-defaults
可以避免 my.cnf 里配了 [client] 某些 mysqlbinlog 没有的参数导致 mysqlbinlog 失败
2. -v 不加,只显示行格式(即那一串字符串),无法得到伪 SQL :BEGIN ; # at 2203 # at 2283 #220411 16:35:16 server id 8027 end_log_pos 2343 CRC32 0xdd9758d2 Table_map: `test`.`zhouwb` mapped to number 88 # at 2343 #220411 16:35:16 server id 8027 end_log_pos 2405 CRC32 0xd3f30671 Write_rows: table id 88 flags: STMT_END_F BINLOG ' ROhTYhNbHwAAPAAAACcJAAAAAFgAAAAAAAEABHRlc3QABnpob3V3YgACAw8CUAACAQEAAgP8/wDS WJfd ROhTYh5bHwAAPgAAAGUJAAAAAFgAAAAAAAEAAgAC/wAGAAAAB2JlaWppbmcABwAAAAh0aWFuamlu Z3EG89M= '; # at 2405 #220411 16:35:16 server id 8027 end_log_pos 2436 CRC32 0xd8de314b Xid = 22 COMMIT;加 -v,从行格式中重建伪SQL(带注释),不显示 binlog_rows_query_log_events 参数效果:
BEGIN ; # at 2203 # at 2283 #220411 16:35:16 server id 8027 end_log_pos 2343 CRC32 0xdd9758d2 Table_map: `test`.`zhouwb` mapped to number 88 # at 2343 #220411 16:35:16 server id 8027 end_log_pos 2405 CRC32 0xd3f30671 Write_rows: table id 88 flags: STMT_END_F BINLOG ' ROhTYhNbHwAAPAAAACcJAAAAAFgAAAAAAAEABHRlc3QABnpob3V3YgACAw8CUAACAQEAAgP8/wDS WJfd ROhTYh5bHwAAPgAAAGUJAAAAAFgAAAAAAAEAAgAC/wAGAAAAB2JlaWppbmcABwAAAAh0aWFuamlu Z3EG89M= '; ### INSERT INTO `test`.`zhouwb` ### SET ### @1=6 ### @2='beijing' ### INSERT INTO `test`.`zhouwb` ### SET ### @1=7 ### @2='tianjing' # at 2405 #220411 16:35:16 server id 8027 end_log_pos 2436 CRC32 0xd8de314b Xid = 22 COMMIT;加 -vv,从行格式中重建伪SQL并添加字段数据类型的注释,可以显示 binlog_rows_query_log_events 参数效果:
BEGIN ; # at 2203 #220411 16:35:16 server id 8027 end_log_pos 2283 CRC32 0xd4ef1b64 Rows_query # insert into zhouwb values(6, 'beijing'), (7, 'tianjing') # at 2283 #220411 16:35:16 server id 8027 end_log_pos 2343 CRC32 0xdd9758d2 Table_map: `test`.`zhouwb` mapped to number 88 # at 2343 #220411 16:35:16 server id 8027 end_log_pos 2405 CRC32 0xd3f30671 Write_rows: table id 88 flags: STMT_END_F BINLOG ' ROhTYh1bHwAAUAAAAOsIAACAADhpbnNlcnQgaW50byB6aG91d2IgdmFsdWVzKDYsICdiZWlqaW5n JyksICg3LCAndGlhbmppbmcnKWQb79Q= ROhTYhNbHwAAPAAAACcJAAAAAFgAAAAAAAEABHRlc3QABnpob3V3YgACAw8CUAACAQEAAgP8/wDS WJfd ROhTYh5bHwAAPgAAAGUJAAAAAFgAAAAAAAEAAgAC/wAGAAAAB2JlaWppbmcABwAAAAh0aWFuamlu Z3EG89M= '; ### INSERT INTO `test`.`zhouwb` ### SET ### @1=6 ### @2='beijing' ### INSERT INTO `test`.`zhouwb` ### SET ### @1=7 ### @2='tianjing' # at 2405 #220411 16:35:16 server id 8027 end_log_pos 2436 CRC32 0xd8de314b Xid = 22 COMMIT;3. 加 --base64-output=decode-rows
不显示行格式,如果同时加 -v 参数,可以从行格式中解码为带注释的伪SQL:
BEGIN ; # at 2203 #220411 16:35:16 server id 8027 end_log_pos 2283 CRC32 0xd4ef1b64 Rows_query # insert into zhouwb values(6, 'beijing'), (7, 'tianjing') # at 2283 #220411 16:35:16 server id 8027 end_log_pos 2343 CRC32 0xdd9758d2 Table_map: `test`.`zhouwb` mapped to number 88 # at 2343 #220411 16:35:16 server id 8027 end_log_pos 2405 CRC32 0xd3f30671 Write_rows: table id 88 flags: STMT_END_F ### INSERT INTO `test`.`zhouwb` ### SET ### @1=6 ### @2='beijing' ### INSERT INTO `test`.`zhouwb` ### SET ### @1=7 ### @2='tianjing' # at 2405 #220411 16:35:16 server id 8027 end_log_pos 2436 CRC32 0xd8de314b Xid = 22 COMMIT;4. --skip-gtids
不保留 GTID 事件信息,这样回放 binlog 时会跟执行新事务一样,生成新的 GTID。对比如下:
## 带 --skip-gtids [root@easydb data]# /root/opt/mysql/8.0.27/bin/mysqlbinlog --no-defaults -vv --base64-output=decode-rows --skip-gtids mysql-bin.000008 | grep GTID ; ## 不带 --skip-gtids,可以看到 GTID event [root@easydb data]# /root/opt/mysql/8.0.27/bin/mysqlbinlog --no-defaults -vv --base64-output=decode-rows mysql-bin.000008 | grep GTID #220411 15:40:09 server id 8027 end_log_pos 196 CRC32 0x3322bc7b Previous-GTIDs #220411 15:46:17 server id 8027 end_log_pos 275 CRC32 0xa846d089 GTID last_committed=0 sequence_number=1 rbr_only=yes original_committed_timestamp=1649663177532042 immediate_commit_timestamp=1649663177532042 transaction_length=348 SET @@SESSION.GTID_NEXT= '00008027-0000-0000-0000-000000008027:234929';–include-gtids 只解析出指定的 GTID 的事务:
[root@easydb data]# /root/opt/mysql/8.0.27/bin/mysqlbinlog --no-defaults -vv --base64-output=decode-rows --include-gtids='00008027-0000-0000-0000-000000008027:234930-234932' mysql-bin.000008 | grep GTID #220411 15:40:09 server id 8027 end_log_pos 196 CRC32 0x3322bc7b Previous-GTIDs #220411 15:46:52 server id 8027 end_log_pos 623 CRC32 0x88a5ac62 GTID last_committed=1 sequence_number=2 rbr_only=yes original_committed_timestamp=1649663212297057 immediate_commit_timestamp=1649663212297057 transaction_length=350 SET @@SESSION.GTID_NEXT= '00008027-0000-0000-0000-000000008027:234930'; #220411 15:47:36 server id 8027 end_log_pos 973 CRC32 0x1c67959b GTID last_committed=2 sequence_number=3 rbr_only=yes original_committed_timestamp=1649663256370735 immediate_commit_timestamp=1649663256370735 transaction_length=384 SET @@SESSION.GTID_NEXT= '00008027-0000-0000-0000-000000008027:234931'; #220411 15:51:04 server id 8027 end_log_pos 1357 CRC32 0x96a24670 GTID last_committed=3 sequence_number=4 rbr_only=yes original_committed_timestamp=1649663464924883 immediate_commit_timestamp=1649663464924883 transaction_length=422 SET @@SESSION.GTID_NEXT= '00008027-0000-0000-0000-000000008027:234932'; SET @@SESSION.GTID_NEXT= 'AUTOMATIC' ;不解析指定的 GTID 的事务 --exclude-gtids 利用 Linux 的管道命令解析
个人常用的 Linux 下解析命令:
/root/opt/mysql/8.0.27/bin/mysqlbinlog --no-defaults -vv --base64-output=decode-rows --database test --skip-gtids=true mysql-bin.000008 | grep -C 1 -i "delete from zhouwb" > /tmp/delete.log
- no-defaults:避免 my.cnf 里配了 [client] 某些 mysqlbinlog 没有的参数导致 mysqlbinlog 失败。
- base64-output=decode-rows -vv:显示具体 SQL 语句。
- database:只列出该数据库下的行数据,但无法过滤 Rows_query_event。
- skip-gtids=true:忽略 GTID 显示。
- mysql-bin.000008:需要解析的 binlog 日志。
- grep -C 1 -i “delete from zhouwb”:通过管道命令筛选出所需 SQL 及执行时间。
- /tmp/delete.log:将结果导入到日志文件,方便查看。
效果展示:
[root@easydb data]# /root/opt/mysql/8.0.27/bin/mysqlbinlog --no-defaults -vv --base64-output=decode-rows --database test --skip-gtids=true mysql-bin.000008 | grep -C 1 -i "delete from zhouwb" #220411 16:34:34 server id 8027 end_log_pos 1909 CRC32 0x95943ed8 Rows_query # delete from zhouwb where id = 6 # at 1909因为有悔,所以披星戴月;因为有梦,所以奋不顾身! 个人博客首发:easydb.net 微信公众号:easydb 关注我,不走丢!



