Reply events using MySQL binlog - ppair/articles GitHub Wiki

利用 MySQL binlog 重放日志.

背景

利用 MySQL binlog来重放日志是一个常见的操作. 但是有时候我们需要作一些过滤, 比如删掉其中某几个事务. 本文简单介绍 mysqlbinlog 工具在此流程中的用法. 相比与解析成SQL语句,这个方法比较简单而且不用考虑编码/特殊字符转换的问题.

mysqlbinlog

这个工具是官方自带的, 最基本的命令方式是 "mysqlbinlog + binlog文件".

首先需要确保版本兼容, 一般是向下兼容, 比如用5.5版本的mysqlbinlog 就解析不了5.6的日志文件.如果你执行后发现一开始就有类似"Sanity check failed"这样的错误,一般是版本问题.

文本基本结构

如果只是为了全量执行, 只需要 mysqlbinlog + 文件名 | mysql -u -p .... 即可.

但是如果有过滤需求,比如需要一个个事务人肉确认, 则一般会用mysqlbinlog -vv > tmpfile 先导到文件,完成编辑后再通过管道,或者source命令在目标DB中执行.

得到的文本文件的基本结构:

  1. 若干个SET 命令, 设置环境变量

  2. DELIMITER /!/; 这个是用于设置后面的风格符, 避免语SQL语句的分号干扰, 或者有存储过程造成分隔符歧义.

  3. format description. 用于表示接下来的命令是日志文件,而不(只)是普通的SQL语句.一般是形如这样的一段:a

  4. 事务 1 .... 事务 N

  5. DELIMITER ; 设置回默认的分隔符

  6. ROLLBACK /* added by mysqlbinlog */; 这个注释已经说明了, 并不是日志本身有ROLLBACK, 而是mysqlbinlog工具本身生成的. 目的是在最后一个事务异常的时候, 执行一半的事务可以被马上回滚. 一个binlog末尾事务不写完全, 常见就是异常crash和磁盘空间满.

事务基本结构

编辑文件操作

  1. 从上面的分析可以看出, 如果是要从一个完整的生成文本中删除一个事务, 只要从从SET TIMESTAMP开始到COMMIT删除即可.

  2. 如果要从中取部分日志单独执行, 则手动创建的文件,一定要先包含format description和所有SET命令., 再将事务日志一个个帖进去.

  3. 对于5.6的binlog,如果主库开了GTID, 在回放时,如果是确定要执行的语句, 要删除所有包含 SET @@SESSION.GTID=xxxxxxx 的行.