MySQL 数据恢复系列一:数据闪回工具 binlog2sql

由于个人能力有限,文中可能存在错误,并且很多细节没有深入分析,欢迎批评指正。

1.解决哪些问题?

1)数据误删
2)binlog 日志解析

2.前置条件

1)log_bin 为 ON , binlog_format 为 ROW ( Mixed 也可以),且 binlog_row_image 为 full 或 noblog ,默认为 full ;

mysql> show variables where variable_name in ('log_bin','binlog_format','binlog_row_image');
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| log_bin          | ON    |
| binlog_format    | ROW   |
| binlog_row_image | FULL  |
+------------------+-------+

2)必须开启 MySQL Server ,离线模式无法解析;
3)用来闪回数据的 user 需要的最小权限集合。
select, super/replication client, replication slave

select:读取 server 端 information_schema.COLUMNS 表,获取表结构的元信息,拼接成可视化的sql语句。
super/replication client:两个权限都可以,需要执行 SHOW MASTER STATUS , 获取 server 端的 binlog 列表。
replication slave:通过 BINLOG_DUMP 协议获取 binlog 内容的权限。

授权命令如下:

mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO [user]@'%' identified by '[password]';

3.软件部署

3.1.下载软件包

binlog2sql.tar.gz (请自行 git )

3.2.安装

shell> tar -zxvf binlog2sql.tar.gz
shell> cd binlog2sql/binlog2sql_dependencies/
shell> tar -zxvf setuptools-0.6c11.tar.gz
shell> cd setuptools-0.6c11
shell> python setup.py install
shell> cd ..
shell> tar -zxvf pip-9.0.1.tar.gz
shell> cd pip-9.0.1
shell> python setup.py install
shell> cd ..
shell> pip install *.whl mysql-replication-0.9.tar.gz

4.使用帮助

1)mysql 连接配置

-h host; -P port; -u user; -p password

2)解析模式

--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

3)解析范围控制

--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' 。可选,默认不过滤。

4)对象过滤

-d, --databases 				只解析目标 db 的 sql ,多个库用空格隔开,如 -d db1 db2 。可选,默认为空。
-t, --tables 					只解析目标 table 的 sql ,多张表用空格隔开,如 -t tbl1 tbl2 。可选,默认为空。
--only-dml 					只解析 dml,忽略ddl 。可选,默认 TRUE。
--sql-type 					只解析指定类型,支持 INSERT, UPDATE, DELETE 。多个类型用空格隔开,可选。默认为增删改都解析。用了此参数但没填任何类型,则三者都不解析。

5.命令示例

1)查看某个时间段内对某表的 sql 执行记录

shell> python binlog2sql.py -h[host] -P[port] -u[user] -p'[password]' --start-file='[binlog_file_name]' -d[table_schema] -t[table_name] --start-datetime='[%Y-%m-%d %H:%M:%S]' --stop-datetime='[%Y-%m-%d %H:%M:%S]' 

2)结合上述命令确定事务及其提交 position ,并生产目标事务的回滚 sql

shell> python binlog2sql.py -h[host] -P[port] -u[user] -p'[password]' --start-file='[binlog_file_name]' -d[table_schema] -t[table_name] --start-position='[position]' --stop-position='[position]'  -B

6.案例测试

# 创建测试表 t1
mysql> show create table t1\G
*************************** 1. row ***************************
    Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`employee` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_employee` (`employee`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
	
# 插入测试数据
mysql> insert into t1 (employee) values ('111'),('222'),('333');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

# 查看 t1 表当前数据
mysql> select * from t1;
+----+----------+
| id | employee |
+----+----------+
|  1 | 111      |
|  2 | 222      |
|  3 | 333      |
+----+----------+
3 rows in set (0.01 sec)

# 刷新 binlog 日志,生成新的日志
mysql> flush logs;
Query OK, 0 rows affected (0.10 sec)

# 删除 t1 表所有数据
mysql> delete from t1;
Query OK, 3 rows affected (0.00 sec)

# 查看 t1 表数据
mysql> select * from t1;
Empty set (0.00 sec)

# 查看 binlog 文件
mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000013
         Position: 520
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 7c54e776-807d-11eb-b035-fa163ee04d48:1-1331,
7d5edd3b-807d-11eb-ae54-fa163ee4c1f8:1
1 row in set (0.00 sec)

# 使用前文的命令示例,补全信息,查看对 t1 表的 sql 执行记录
[root@dbtest01 binlog2sql]# python binlog2sql.py -h127.1 -P3306 -uroot -p'******' --start-file='mysql-bin.000013' -ddbtest01 -tt1 --start-datetime='2021-08-18 14:00:00' --stop-datetime='2021-08-18 15:00:00'
DELETE FROM `dbtest01`.`t1` WHERE `employee`='111' AND `id`=1 LIMIT 1; #start 299 end 489 time 2021-08-18 14:21:26
DELETE FROM `dbtest01`.`t1` WHERE `employee`='222' AND `id`=2 LIMIT 1; #start 299 end 489 time 2021-08-18 14:21:26
DELETE FROM `dbtest01`.`t1` WHERE `employee`='333' AND `id`=3 LIMIT 1; #start 299 end 489 time 2021-08-18 14:21:26

# 根据执行记录中的 position 生成回滚 sql
[root@dbtest01 binlog2sql]# python binlog2sql.py -h127.1 -P3306 -uroot -p'******' --start-file='mysql-bin.000013' -ddbtest01 -tt1 --start-position='299' --stop-position='489'  -B
INSERT INTO `dbtest01`.`t1`(`employee`, `id`) VALUES ('333', 3); #start 299 end 489 time 2021-08-18 14:21:26
INSERT INTO `dbtest01`.`t1`(`employee`, `id`) VALUES ('222', 2); #start 299 end 489 time 2021-08-18 14:21:26
INSERT INTO `dbtest01`.`t1`(`employee`, `id`) VALUES ('111', 1); #start 299 end 489 time 2021-08-18 14:21:26

# 根据误删时间范围生成回滚 sql
[root@dbtest01 binlog2sql]# python binlog2sql.py -h127.1 -P3306 -uroot -p'******' --start-file='mysql-bin.000013' -ddbtest01 -tt1 --start-datetime='2021-08-18 14:00:00' --stop-datetime='2021-08-18 15:00:00'  -B
INSERT INTO `dbtest01`.`t1`(`employee`, `id`) VALUES ('333', 3); #start 299 end 489 time 2021-08-18 14:21:26
INSERT INTO `dbtest01`.`t1`(`employee`, `id`) VALUES ('222', 2); #start 299 end 489 time 2021-08-18 14:21:26
INSERT INTO `dbtest01`.`t1`(`employee`, `id`) VALUES ('111', 1); #start 299 end 489 time 2021-08-18 14:21:26

# 将上述回滚 sql 导出文件 rollback.sql,导入数据库
mysql>source /backup/rollback.sql;

# 查看 t1 表数据
mysql> select * from t1;
+----+----------+
| id | employee |
+----+----------+
|  1 | 111      |
|  2 | 222      |
|  3 | 333      |
+----+----------+
3 rows in set (0.01 sec)

7.其他

该工具本身的核心代码比较少,主要是在 pymysqlreplication 的基础上进行了二次开发。pymysqlreplication 实现了 MySQL 复制协议,可捕捉不同类型的 EVENT 事件。

具体可参考:https://github.com/noplay/python-mysql-replication

注意事项:
1)binlog2sql 强烈依赖于 MySQL 复制协议,如果复制协议发生改变,则该工具将不可用。虽然,复制协议发生改变的可能性很小(一般都会保持向前兼容),但相对而言,自带的 mysqlbinlog 肯定更懂 binlog ,基于 mysqlbinlog 解析后的结果进行处理,可完全屏蔽复制协议等底层细节。
2)用 python 来解析文本格式的 binlog ,本身也不是件难事。比如, update 语句在 binlog 中的对应的文本,在得到表结构的情况下,基本上可离线解析。

8.参考资料

MySQL下实现闪回的设计思路 (MySQL Flashback Feature)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQLbinlog是一种二进制日志文件,用于记录数据库的修改操作。当数据库出现故障时,可以通过binlog来进行数据恢复MySQL提供了多种工具来进行binlog数据恢复。其中最常用的工具mysqlbinlogmysqlbinlog是一个命令行工具,用于解析binlog文件,并将其中的SQL语句打印出来。通过mysqlbinlog,可以将binlog中记录的SQL语句重新执行,从而实现数据恢复。 使用mysqlbinlog进行数据恢复的步骤如下: 1. 找到事故发生时的最新的binlog文件和位置。 2. 使用mysqlbinlog命令解析binlog文件: ```shell mysqlbinlog binlog.000001 --start-position=12345 ``` 这将会将binlog文件中从指定位置开始的所有SQL语句输出到终端。 3. 检查输出的SQL语句,确认其正确性,并逐条重新执行,以恢复数据。 除了mysqlbinlog工具外,还有其他一些第三方的工具可以进行binlog数据恢复。例如,Binlog Explorer、Binlog Viewer等工具提供了更加友好的图形界面,方便操作和查看binlog文件。 需要注意的是,在使用binlog进行数据恢复时,要确保事故发生后的binlog文件没有被删除或覆盖,否则无法完全恢复数据。另外,对于大规模的数据库,binlog数据恢复可能比较耗时和复杂,需要谨慎操作。 总而言之,mysqlbinlog是一种常用的binlog数据恢复工具,通过解析binlog文件中的SQL语句,可以重新执行这些SQL语句以恢复数据。此外,还有其他一些第三方工具可供选择。在进行binlog数据恢复时,需要注意保留好binlog文件,并进行逐条确认和执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值