暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mysql问题小记之_使用binlog2sql解析binlog日志

山佳数峰寻道 2025-08-22
197

什么是binlog2sql

binlog2sql 这是一个开源 Python 工具,专门为解决 mysqlbinlog 的痛点而生。它可以直接从 ROW 格式的 binlog 中解析出原始SQL、回滚SQL、带SQL类型的SQL。

GitHub 地址: https://github.com/danfengcao/binlog2sql

优势:

  • 直接输出易于阅读的 SQL 语句。
  • 支持生成回滚 SQL(用于快速恢复误操作数据)。
  • 支持过滤(库、表、时间、位置、SQL 类型)。
  • 输出结果更干净,无需处理注释。

安装操作步骤

话不多说,我们直接开始进行操作:

首先要确保Linux服务器上有git命令,并且没有网络限制可以访问到github,但是在生产环境中一般不会主动访问外网,可以下载下来进行放到服务器上:

本次直接使用git 进行clone :

     git clone https://github.com/danfengcao/binlog2sql.git 
     cd binlog2sql
     #进行安装依赖
     pip install -r requirements.txt

      #如果 yum 无法安装,这是最直接有效的方法:
      curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py
        #运行安装脚本(使用 python 2.7)
        python get-pip.py
        #执行结果如图
        然后继续进行安装依赖:

        至此binlog2sql,就可以使用了。在README.md里面有如下内容:

          ### MySQL server必须设置以下参数:
              [mysqld]
              server_id = 1
              log_bin = /var/log/mysql/mysql-bin.log
              max_binlog_size = 1G
              binlog_format = row
              binlog_row_image = full
          ### user需要的最小权限集合:
              select, super/replication client, replication slave
              建议授权
              GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 
          **权限说明**
          * select:需要读取server端information_schema.COLUMNS表,获取表结构的元信息,拼接成可视化的sql语句
          * super/replication client:两个权限都可以,需要执行'SHOW MASTER STATUS', 获取server端的binlog列表
          * replication slave:通过BINLOG_DUMP协议获取binlog内容的权限
          ### 基本用法
          **解析出标准SQL**
          ```bash
          shell> python binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t test3 test4 --start-file='mysql-bin.000002'
          输出:
          INSERT INTO `test`.`test3`(`addtime`, `data`, `id`) VALUES ('2016-12-10 13:03:38', 'english', 4); #start 570 end 736
          UPDATE `test`.`test3` SET `addtime`='2016-12-10 12:00:00', `data`='中文', `id`=3 WHERE `addtime`='2016-12-10 13:03:22' AND `data`='中文' AND `id`=3 LIMIT 1; #start 763 end 954
          DELETE FROM `test`.`test3` WHERE `addtime`='2016-12-10 13:03:38' AND `data`='english' AND `id`=4 LIMIT 1; #start 981 end 1147
          ```
          **解析出回滚SQL**
          ```bash
          shell> python binlog2sql.py --flashback -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttest3 --start-file='mysql-bin.000002' --start-position=763 --stop-position=1147
          输出:
          INSERT INTO `test`.`test3`(`addtime`, `data`, `id`) VALUES ('2016-12-10 13:03:38', 'english', 4); #start 981 end 1147
          UPDATE `test`.`test3` SET `addtime`='2016-12-10 13:03:22', `data`='中文', `id`=3 WHERE `addtime`='2016-12-10 12:00:00' AND `data`='中文' AND `id`=3 LIMIT 1; #start 763 end 954
          ```
          ### 选项
          **mysql连接配置**
          -h host; -P port; -u user; -p password
          **解析模式**
          --stop-never 持续解析binlog。可选。默认False,同步至执行命令时最新的binlog位置。
          -K, --no-primary-key 对INSERT语句去除主键。可选。默认False
          -B, --flashback 生成回滚SQL,可解析大文件,不受内存限制。可选。默认False。与stop-never或no-primary-key不能同时添加。
          --back-interval -B模式下,每打印一千行回滚SQL,加一句SLEEP多少秒,如不想加SLEEP,请设为0。可选。默认1.0。
          **解析范围控制**
          --start-file 起始解析文件,只需文件名,无需全路径 。必须。
          --start-position/--start-pos 起始解析位置。可选。默认为start-file的起始位置。
          --stop-file/--end-file 终止解析文件。可选。默认为start-file同一个文件。若解析模式为stop-never,此选项失效。
          --stop-position/--end-pos 终止解析位置。可选。默认为stop-file的最末位置;若解析模式为stop-never,此选项失效。
          --start-datetime 起始解析时间,格式'%Y-%m-%d %H:%M:%S'。可选。默认不过滤。
          --stop-datetime 终止解析时间,格式'%Y-%m-%d %H:%M:%S'。可选。默认不过滤。
          **对象过滤**
          -d, --databases 只解析目标db的sql,多个库用空格隔开,如-d db1 db2。可选。默认为空。
          -t, --tables 只解析目标table的sql,多张表用空格隔开,如-t tbl1 tbl2。可选。默认为空。
          --only-dml 只解析dml,忽略ddl。可选。默认False。
          --sql-type 只解析指定类型,支持INSERT, UPDATE, DELETE。多个类型用空格隔开,如--sql-type INSERT DELETE。可选。默认为增删改都解析。用了此参数但没填任何类型,则三者都不解析。

          本次因为时间比较久,涉及多个binlog文件因此我们使用脚本进行批量解析:

          创建脚本内容如下:

            #!/bin/bash
            # 定义连接参数和输出文件
            HOST="数据库IP"
            USER="dbusername"
            PASSWORD="userpasswd"
            PORT="3306"
            OUTPUT_FILE="all_binlogs_output.sql"


            # 定义时间区间限制(请根据实际需求修改)
            START_DATETIME="解析开始时间"  # 开始时间
            # 定义要解析的数据库(可以是一个或多个,用逗号分隔)
            DATABASE="databasename"  # 请替换为实际的数据库名
            TABLE_NAME="table_name"  # 指定表
            # 清空或创建最终输出文件
            > "$OUTPUT_FILE"


            # 定义一个包含所有需要解析的 binlog 文件的数组
            # 将 mysql-bin.000001 到 mysql-bin.000003 加入数组
            binlogs=("mysql-bin.000067" "mysql-bin.000068" "mysql-bin.000069" "mysql-bin.000070" "mysql-bin.000071")


            # 循环遍历数组中的每一个 binlog 文件
            for binlog in "${binlogs[@]}"; do
              echo "正在解析 binlog 文件: $binlog ..."
              # 执行 binlog2sql 命令,并将输出追加到总文件
              python data/tool/binlog2sql/binlog2sql/binlog2sql.py \
                -h "$HOST" -u "$USER" -p "$PASSWORD" -P "$PORT" \
                --start-file "$binlog" \
            --start-datetime="$START_DATETIME" \
            -d "$DATABASE" \
            -t "$TABLE_NAME" \
                >> "$OUTPUT_FILE"


              # 检查上一个命令是否执行成功
              if [ $? -eq 0 ]; then
                echo "成功完成: $binlog"
              else
                echo "解析失败: $binlog" >&2
                exit 1
              fi
            done


            echo "所有 binlog 文件解析完成!结果已保存到: $OUTPUT_FILE"


            授予执行权限之后,可以直接 sh binshell.sh执行,本次使用nohup进行后台执行,命令如下:

              nohup sh binshell.sh &
              #查看内容nohup内容:

              等待一会儿,分析完成后,可以进行查看all_binlogs_output.sql

              binlog2sql解析binlog日志,分享就到这里了。

              总结binlog2sql优势:

              高效精准:直接解析ROW格式binlog为SQL,无需手动拼接

              功能强大:支持回滚SQL生成,是数据恢复的利器

              过滤灵活:提供多种维度的过滤选项

              输出整洁:生成易于阅读和处理的纯SQL语句

              开源免费:无需额外成本,可自定义扩展

              PS:感谢github大佬们分享工具

              文末附一张和mysqlbinlog的功能对比:
              此上,仅个人观点。


              文章转载自山佳数峰寻道,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论