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

DML 误操作?MySQL 闪回工具大盘点

21

推荐一篇爱可生开源社区的文章。本文约 2500 字,预计阅读需要 9 分钟。


正文如下:


操作数据库时,如果不慎执行了 DML 误操作,闪回工具可以回滚这类 DML 误操作。

闪回之前

在使用闪回工具之前,需要明确几个小问题:

哪些 SQL 类型可以使用闪回工具?

可以使用闪回工具回滚的 DML 类型包括:DELETE、INSERT、UPDATE,不支持 DDL。

需要满足哪些条件才能使用?

闪回前还有一些条件,相关参数满足条件(binlog_row_image=full
binlog_format=row
),且误操作 DML 后,表结构没有增删列(因为 binlog 中不含表字段名)。

误操作一定要用工具么?

如果 DML 操作涉及的数据量较小,则推荐直接在应用侧执行闪回语句效率更高,但闪回语句需要经过应用侧确认之后,在应用层执行。

有哪些闪回工具推荐?

目前比较主流的 MySQL 闪回工具有 binlog2sql[1]my2sql[2]MyFlash[3] 三款。

基本信息


binlog2sql
my2sql
MyFlash
MySQL
支持版本
5.7
5.7 8.0
5.7
离线解析
语言
Python
Go
C
最后更新时间
2018.10
2022.11
2020.11

功能特点

binlog2sql:回滚 DML,解析出回滚或原始 SQL。

my2sql:回滚 DML,解析出回滚或原始 SQL。还可以通过 binlog 统计 DML、长事务与大事务分析。

MyFlash:回滚 DML,生成 binlog 类型的回滚文件。

综合以上,推荐使用 my2sql 回滚 DML。下面我们着重介绍 MyFlash 和 my2sql 两款工具的使用。

MyFlash

MyFlash 是由美团点评公司技术工程部开发维护的一个回滚 DML 操作的工具。该工具通过解析 v4 版本的 binlog,完成回滚操作。相对已有的回滚工具,其增加了更多的过滤选项,让回滚更加容易。该工具已经在美团点评内部使用。

MyFlash 可以完全离线,因为只是生成回滚 binlog 文件。但只支持单个文件解析。

推荐方式:指定 GTID 范围,等同于时间点和 Pos 点。

使用方式

show master status\G
File: mysql-bin.000014
Executed_Gtid_Set: 52875cf3-e9d3-11ef-88ab-02000aba3d09:120764

checksum table test_table;
+-------------------+------------+
| Table             | Checksum   |
+-------------------+------------+
| test01.test_table | 1479091061 |
+-------------------+------------+

复制

模拟误操作,事务号范围 120765-120766。

update test_table set blob_field='Tom' where id <900;
update test_table set blob_field='Jreey' where id >900 and id<1000;

复制

执行回滚,有事务号使用 --include-gtids
。默认生成的回滚文件名为:binlog_output_base.flashback

# cd  MyFlash-master/binary/
./flashback --binlogFileNames=mysql-bin.000014 --databaseNames=test01 --tableNames=test_table --sqlTypes='delete,insert,update' --include-gtids='52875cf3-e9d3-11ef-88ab-02000aba3d09:120765-120766'

复制

应用回滚的 binlog 文件,会记录本地 gtid 事务号(skip-gtids
不能避免记录事务号,只是为了防止 SQL_MODE=ON
 报错)。

mysqlbinlog -vv binlog_output_base.flashback --skip-gtids|mysql -uroot -p

复制

验证结果一致!

checksum table test_table;
+-------------------+------------+
| Table             | Checksum   |
+-------------------+------------+
| test01.test_table | 1479091061 |
+-------------------+------------+

复制

⚠️ 注意事项

  1. binlogFileNames 指定需要回滚的 binlog 文件,目前只支持单个文件。
  2. sqlTypes 支持写一个类型,如 --sqlTypes='delete'
  3. include-gtids 指定需要回滚的 gtid,支持 gtid 的单个和范围两种形式。
  4. exclude-gtids 指定不需要回滚的 gtid,用法同 include-gtids

my2sql

my2sql 是 Go 版的 MySQL binlog 解析工具,通过解析 MySQL binlog ,可以生成原始 SQL、回滚 SQL、去除主键的 INSERT SQL 等,也可以生成 DML 统计信息。基于 my2fback、binlog_rollback 工具二次开发而来。2.0 版本开始支持 caching_sha2_password 插件,推荐使用此版本。

my2sql 根据需要原始 SQL 或回滚 SQL,对应 work-type
 参数,支持指定时间点(效果等同于 GTID 范围)。

  • 生成原始 SQL:-work-type 2sql
  • 生成回滚 SQL:-work-type rollback

推荐方式:明确指定开始时间和结束时间,配合 file 模式时,只会读取表信息,对库入侵性最小。

核心参数

  • -start-file:指定开始读取的 binlog 文件名称。

    虽然也有 -stop-file
     参数,指定停止读取的 binlog 文件名称,但一般不用,因为 start-file
     配合时间就可以定位出误操作执行的区间。

  • -work-type:工作类型。

    • 2sql:生成原始 SQL。
    • rollback:生成回滚 SQL。
    • stats:只统计 DML、事务信息。
  • -mode:获取 binlog 文件的模式。

    • repl:伪装成从库解析 binlog 文件(需要拉取)(默认)。
    • file:离线解析 binlog 文件。推荐使用,因为以下信息可以证明 file 模式只是查看了表信息。

不同模式连接数据库后的操作信息

unsetunsetrepl 模式unsetunset
admin@127.0.0.1 on  using TCP/IP
SET NAMES utf8mb4
SET autocommit=true
admin@127.0.0.1 on  using TCP/IP
SHOW GLOBAL VARIABLES LIKE 'BINLOG_CHECKSUM'
SET @master_binlog_checksum='NONE'
SET @slave_uuid = 'ff2f78c5-fb2c-11ef-a0eb-02000aba3d09', @replica_uuid = 'ff2f78c5-fb2c-11ef-a0eb-02000aba3d09'
 Binlog Dump       Log: 'mysql-bin.000004'  Pos: 4
Query     SHOW COLUMNS FROM `test01`.`t01`
Query     SHOW INDEX FROM `test01`.`t01`

复制
unsetunsetfile 模式unsetunset
admin@127.0.0.1 on  using TCP/IP
SET NAMES utf8mb4
SET autocommit=true
SHOW COLUMNS FROM `test01`.`t01`
SHOW INDEX FROM `test01`.`t01`

复制
  • -local-binlog-file:binlog 文件路径。

    当指定 -mode file
     参数时,需要指定 -local-binlog-file
     binlog 文件的相对路径或绝对路径,可以连续解析多个 binlog 文件,只需要指定起始文件名,工具会自动持续解析下个文件。

下面我们将先后介绍 生成回滚 SQL 和原始 SQL 两种工作类型。

生成回滚 SQL

生成的 SQL 文件,导入会更新 GTID。

⚠️ 注意事项

可使用 set+source 避免更新 GTID。

show masterstatus\G
File: mysql-bin.000006
Position255561
52875cf3-e9d3-11ef-88ab-02000aba3d09:1-34

selectcount(*) from t01;checksumtable t01;
+----------+
| count(*) |
+----------+
|     1000 |
+----------+
+------------+------------+
| Table      | Checksum   |
+------------+------------+
| test01.t01 | 1658863531 |
+------------+------------+

复制

模拟数据误操作 DELETE,删除了 499 行。

delete from t01 where id < 500;

复制

找到误删除的开始的时间,如 250307 14:12:06
,根据误操作时间定位到 binlog 文件,直接搜索 🔍 误操作的语句也可以。

mysqlbinlog --base64-output=decode-rows -vv --database test01 mysql-bin.000006 |grep  -C 10 -i "Rows_query" |grep -C 10    -i "t01" |grep -C 10 -i "delete" > t01_detele.log
#250307 14:12:06 server id 110  end_log_pos 255759      Rows_query
# delete from t01 where id < 500

复制

结束的时间,如 250307 14:38:11
(需要找到下一个事务的开始时间),往下搜索 🔍 COMMIT 或是 SESSION.GTID_NEXT 或是 GTID 信息。

#250307 14:12:06 server id 110  end_log_pos 265277      Xid = 445
COMMIT/*!*/;
# at 265277
#250307 14:38:11 server id 110  end_log_pos 265350

复制

以下方案二选一。

方案一

直接读取 binlog 文件解析时(-mode file
),binlog 文件相对路径或绝对路径。

./my2sql -user admin -password 123456 -host 127.0.0.1  -port 3313 -mode file -local-binlog-file ./mysql-bin.000004  -work-type rollback  -start-file mysql-bin.000004 -start-datetime "2025-03-07 14:12:06" -stop-datetime "2025-03-07 14:38:11" -add-extraInfo -output-dir ./tmpdir

复制

方案二

伪装成从库解析 binlog。

./my2sql -user admin -password 123456 -host 127.0.0.1  -port 3313  -work-type rollback  -start-file mysql-bin.000004 -start-datetime "2025-03-07 14:12:06" -stop-datetime "2025-03-07 14:38:11" -add-extraInfo -output-dir ./tmpdir01

复制

两种方案执行结果一样,共生成了 3 个文件。

  • rollback.6.sql
    :回滚 SQL 文件
  • biglong_trx.txt
    :大事务信息
  • binlog_status.txt
    :DML 的统计信息

验证与误删除数据量是否相等。导入验证结果一致。

cat rollback.6.sql |grep "INSERT INTO"|wc -l
499

复制

重定向方式 <
 导入,会记录到 binlog 并增加事务号。可通过 set sql_log_bin=0;
 source 的方式不记录。

set sql_log_bin=0;
source tools/my2sql_test/tmpdir/rollback.6.sql;
select count(*) from t01;checksum table t01;
+----------+
| count(*) |
+----------+
|     1000 |
+----------+
+------------+------------+
| Table      | Checksum   |
+------------+------------+
| test01.t01 | 1658863531 |
+------------+------------+

复制

⚠️ 注意事项

  1. mysqlbinlog 命令解析参数 base64-output=decode-rows
     (可选),作用是将二进制日志中以 Base64 编码存储的行数据解码为可读的文本格式。这样,你在查看二进制日志内容时,就可以直接看到具体的行数据更改,而不是一串 Base64 编码的字符串。
  2. 闪回 SQL 文件中的 # datetime=...
     这行的内容,就是加了参数 -add-extrainfo
     后加入的附加信息,可以获取每个语句执行的具体时间和点位。
  3. my2sql 工具可以增加 -databases
     参数,实现只过滤指定库,默认为全部库。

生成原始 SQL

除了参数 work-type=2sql
,其他参数和生成回滚 SQL 命令一样。

方案一

直接读取 binlog 文件解析。

./my2sql -user admin -password 123456 -host 127.0.0.1  -port 3313 -mode file -local-binlog-file ./mysql-bin.000004  -work-type 2sql  -start-file mysql-bin.000004 -start-datetime "2025-03-07 14:12:06" -stop-datetime "2025-03-07 14:38:11" -add-extraInfo -output-dir ./tmpdir

复制

方案二

伪装成从库解析 binlog。

./my2sql -user admin -password 123456 -host 127.0.0.1  -port 3313  -work-type 2sql  -start-file mysql-bin.000004 -start-datetime "2025-03-07 14:12:06" -stop-datetime "2025-03-07 14:38:11" --add-extraInfo -output-dir ./tmpdir01

复制

两种方案执行结果一样,共生成了 3 个文件。

  • forward.6.sql
    :原始 SQL 文件(原始误操作语句)
  • biglong_trx.txt
    :大事务信息
  • binlog_status.txt
    :DML 的统计信息

查看生成的 biglong_trx.txt
 文件。

cat biglong_trx.txt 
binlog            starttime           stoptime            startpos   stoppos    rows     duration   tables
mysql-bin.000006  2025-03-07_14:12:06 2025-03-07_14:12:06 255636     265277     499      0     [test01.t01(inserts=0, updates=0, deletes=499)]

复制

查看生成的 binlog_status.txt
 文件,会统计每个时间段区间内相关库表所产生的 DML 次数。

cat binlog_status.txt 
binlog            starttime           stoptime            startpos   stoppos    inserts  updates  deletes  database        table               
mysql-bin.000006  2025-03-07_14:12:06 2025-03-07_14:12:06 255759     265250     0        0        499      test01          t01                 

复制

🤔 思考:如何避免误操作?

使用闪回工具只是一种补救措施,安全运维应该在预防误操作上有哪些安排呢?

一个让运维人员睡的安心的数据保障系统(MySQL 版)。

  1. 预防,为了减少数据误删除发生的概率,通过交付基线避免。
  2. 技术回归(时间点恢复 Point-in-Time Recovery)删库删表,万一发生误操作,通过备份和 binlog 回放恢复。
  3. 技术回归(闪回工具)回滚 DML,通过 binlog 恢复。
  4. 技术回归(Undrop-for-innodb) 磁盘文件级别恢复(虽然有些缺陷)。

预防问题发生,然后解决发生的问题,提高运维服务的满意度~

参考资料
[1] 

binlog2sql: https://github.com/danfengcao/binlog2sql

[2] 

my2sql: https://github.com/liuhr/my2sql

[3] 

MyFlash: https://github.com/Meituan-Dianping/MyFlash


本文关键字:#MySQL# #闪回工具# #DML# #my2sql# #MyFlash#


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

评论