文档课题:MySQL恢复delete数据.
1、方案背景
在使用MySQL数据库过程中,难免会因为某种原因导致数据被不小心delete,如果是Oracle数据库,可以运用闪回查询快速恢复数据.
而在MySQL数据库中如何对delete后的数据进行恢复呢?接下来就介绍运用Binlog2sql工具恢复数据.
2、方案展示
数据库:mysql 5.7.36
2.1、确认binlog情况
mysql> show variables like '%log_bin%';
+---------------------------------+-------------------------------+
| Variable_name | Value |
+---------------------------------+-------------------------------+
| log_bin | ON |
| log_bin_basename | /mysql/binlog/mysql-bin |
| log_bin_index | /mysql/binlog/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+-------------------------------+
6 rows in set (0.00 sec)
2.2、建测试数据
mysql> use fruitsDB;
mysql> create table employee (id int not null auto_increment primary key,
dept tinyint not null,
age tinyint not null,
name varchar(30),
create_time datetime not null,
last_login_time datetime
);
mysql> insert into employee values(1,1,25,'leo','2024-10-22 00:00:00','2024-10-22 12:00:00');
mysql> create index idx_dept on employee(dept);
mysql> create index idx_create_time on employee(create_time);
mysql> create index idx_last_login_time on employee(last_login_time);
2.3、delete数据
-- 模拟删除一条数据
mysql> delete from employee where id=1;
2.4、确认BINLOG
[mysql@leo-mysql01 binlog]$ ls -ltr
total 1317088
-rw-r-----. 1 mysql mysql 1593 Dec 24 2023 mysql-bin.000001
-rw-r-----. 1 mysql mysql 154 Dec 24 2023 mysql-bin.000002
-rw-r-----. 1 mysql mysql 154 Dec 24 2023 mysql-bin.000003
-rw-r-----. 1 mysql mysql 154 Dec 24 2023 mysql-bin.000004
-rw-r-----. 1 mysql mysql 201 Dec 24 2023 mysql-bin.000005
-rw-r-----. 1 mysql mysql 177 Dec 24 2023 mysql-bin.000006
-rw-r-----. 1 mysql mysql 1183 Jan 5 2024 mysql-bin.000007
-rw-r-----. 1 mysql mysql 673966352 Jan 5 2024 mysql-bin.000008
-rw-r-----. 1 mysql mysql 177 Jan 5 2024 mysql-bin.000009
-rw-r-----. 1 mysql mysql 154 Mar 29 2024 mysql-bin.000010
-rw-r-----. 1 mysql mysql 202016 Mar 29 2024 mysql-bin.000011
-rw-r-----. 1 mysql mysql 674432721 Mar 30 2024 mysql-bin.000012
-rw-r-----. 1 mysql mysql 154 Mar 31 2024 mysql-bin.000013
-rw-r-----. 1 mysql mysql 154 Apr 11 2024 mysql-bin.000014
-rw-r-----. 1 mysql mysql 154 Jun 13 23:43 mysql-bin.000015
-rw-r-----. 1 mysql mysql 154 Oct 18 22:27 mysql-bin.000016
-rw-r-----. 1 mysql mysql 154 Oct 22 14:06 mysql-bin.000017
-rw-r-----. 1 mysql mysql 154 Oct 22 22:15 mysql-bin.000018
-rw-r-----. 1 mysql mysql 5120 Oct 23 08:39 mysql-bin.000019
-rw-r-----. 1 mysql mysql 7225 Oct 23 16:00 mysql-bin.000020
-rw-r-----. 1 mysql mysql 201 Oct 23 18:07 mysql-bin.000021
-rw-r-----. 1 mysql mysql 682 Oct 23 18:07 mysql-bin.index
-rw-r-----. 1 mysql mysql 1513 Oct 23 18:16 mysql-bin.000022
-- 解析binlog确认SQL语句具体落在哪个binlog.
[mysql@leo-mysql01 binlog]$ mysqlbinlog --no-defaults --base64-output=decode-rows -v -v /mysql/binlog/mysql-bin.000022 | awk '/###/{if($0~/UPDATE|INSERT|DELETE/)count[$2" "$NF]++}END{for(i in count)print i,"\t",count[i]}'|column -t|sort -k3nr
DELETE `fruitsDB`.`employee` 1
INSERT `fruitsDB`.`employee` 1
说明:如上可知SQL语句落在mysql-bin.000022中.
[mysql@leo-mysql01 binlog]$ mysqlbinlog "/mysql/binlog/mysql-bin.000022" --start-datetime="2024-10-23 18:15:00" --stop-datetime="2024-10-23 18:19:00" --base64-output=decode-rows -v > operation.sql
[mysql@leo-mysql01 binlog]$ cat operation.sql
......(省略若干)
#241023 18:15:44 server id 1 end_log_pos 900 CRC32 0xbc60732e Write_rows: table id 131 flags: STMT_END_F
### INSERT INTO `fruitsDB`.`employee`
### SET
### @1=1
### @2=1
### @3=25
### @4='leo'
### @5='2024-10-22 00:00:00'
### @6='2024-10-22 12:00:00'
# at 900
#241023 18:15:44 server id 1 end_log_pos 931 CRC32 0x65b722c6 Xid = 985
COMMIT/*!*/;
# at 931
#241023 18:16:33 server id 1 end_log_pos 996 CRC32 0xaac5664e Anonymous_GTID last_committed=2 sequence_number=3 rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 996
#241023 18:16:33 server id 1 end_log_pos 1113 CRC32 0x2b3c4f21 Query thread_id=50 exec_time=0 error_code=0
SET TIMESTAMP=1729678593/*!*/;
create index idx_dept on employee(dept)
/*!*/;
# at 1113
......(省略若干)
# at 1654
#241023 18:18:21 server id 1 end_log_pos 1714 CRC32 0xe242e87a Table_map: `fruitsDB`.`employee` mapped to number 134
# at 1714
#241023 18:18:21 server id 1 end_log_pos 1775 CRC32 0xa43c8c54 Delete_rows: table id 134 flags: STMT_END_F
### DELETE FROM `fruitsDB`.`employee`
### WHERE
### @1=1
### @2=1
### @3=25
### @4='leo'
### @5='2024-10-22 00:00:00'
### @6='2024-10-22 12:00:00'
# at 1775
#241023 18:18:21 server id 1 end_log_pos 1806 CRC32 0x90984aea Xid = 992
COMMIT/*!*/;
......(省略若干)
2.5、安装依赖包
[root@leo-mysql01 ~]# mount /dev/sr0 /mnt
[root@leo-mysql01 ~]# cat <<EOF>>/etc/yum.repos.d/local.repo
[local]
name=local
baseurl=file:///mnt
gpgcheck=0
enabled=1
EOF
[root@leo-mysql01 ~]# yum makecache
[root@leo-mysql01 ~]# yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc libffi-devel
[root@leo-mysql01 ~]# rpm -q zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc libffi-devel | grep "not installed"
2.6、安装Binlog2sql工具
sftp> lcd F:\BaiduNetdiskDownload\b2sql
sftp> pwd
/root
sftp> put mysql-replication-0.21.tar.gz
sftp> put binlog2sql-master.zip
sftp> put PyMySQL-0.9.3.tar.gz
sftp> put Python-3.8.2.tar.xz
[root@leo-mysql01 ~]# ls -ltr
total 17616
-rw-------. 1 root root 2241 Dec 24 2023 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 Dec 24 2023 initial-setup-ks.cfg
drwxr-xr-x. 2 root root 6 Dec 24 2023 Temployeelates
drwxr-xr-x. 2 root root 6 Dec 24 2023 Downloads
drwxr-xr-x. 2 root root 6 Dec 24 2023 Desktop
drwxr-xr-x. 2 root root 6 Dec 24 2023 Videos
drwxr-xr-x. 2 root root 6 Dec 24 2023 Public
drwxr-xr-x. 2 root root 6 Dec 24 2023 Pictures
drwxr-xr-x. 2 root root 6 Dec 24 2023 Music
drwxr-xr-x. 2 root root 6 Dec 24 2023 Documents
-rw-r--r--. 1 root root 38080 Oct 23 15:52 mysql-replication-0.21.tar.gz
-rw-r--r--. 1 root root 31549 Oct 23 15:52 binlog2sql-master.zip
-rw-r--r--. 1 root root 86715 Oct 23 15:52 PyMySQL-0.9.3.tar.gz
-rw-r--r--. 1 root root 17869888 Oct 23 15:55 Python-3.8.2.tar.xz
[root@leo-mysql01 ~]# tar -xvf Python-3.8.2.tar.xz && cd Python-3.8.2
[root@leo-mysql01 Python-3.8.2]# ./configure --prefix=/usr --with-ensurepip --with-system-ffi
[root@leo-mysql01 Python-3.8.2]# make && make install
[root@leo-mysql01 Python-3.8.2]# python3 --version
Python 3.8.2
[root@leo-mysql01 Python-3.8.2]# pip3 --version
pip 19.2.3 from /usr/lib/python3.8/site-packages/pip (python 3.8)
2.7、安装PyMySQL/mysql-replication
[root@leo-mysql01 Python-3.8.2]# cd ..
[root@leo-mysql01 ~]# mkdir -p ~/.pip
[root@leo-mysql01 ~]# vim ~/.pip/pip.conf
添加以下内容:
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host = mirrors.aliyun.com
[root@leo-mysql01 ~]# pip3 install --upgrade pip
[root@leo-mysql01 ~]# pip3 install PyMySQL-0.9.3.tar.gz
[root@leo-mysql01 ~]# pip3 install mysql-replication-0.21.tar.gz
[root@leo-mysql01 ~]# pip3 list
Package Version
----------------- -------
mysql-replication 0.21
pip 24.2
PyMySQL 0.9.3
setuptools 41.2.0
2.8、解压缩Binlog2sql
[root@leo-mysql01 ~]# unzip binlog2sql-master.zip
[root@leo-mysql01 ~]# mv binlog2sql-master/binlog2sql/ ./
[root@leo-mysql01 ~]# cd binlog2sql
2.9、生成insert语句
-- 将格式为ROW的binlog生成标准SQL
[root@leo-mysql01 binlog2sql]# cp /mysql/binlog/mysql-bin.000022 /root/binlog2sql
[root@leo-mysql01 binlog2sql]# python3 binlog2sql.py -uroot -pmysql_4U -dfruitsDB -t employee --start-file='mysql-bin.000022' --start-datetime='2024-10-23 18:15:00' --only-dml | cut -d '#' -f1 > insert.sql
[root@leo-mysql01 binlog2sql]# cat insert.sql
INSERT INTO `fruitsDB`.`employee`(`id`, `dept`, `age`, `name`, `create_time`, `last_login_time`) VALUES (1, 1, 25, 'leo', '2024-10-22 00:00:00', '2024-10-22 12:00:00');
DELETE FROM `fruitsDB`.`employee` WHERE `id`=1 AND `dept`=1 AND `age`=25 AND `name`='leo' AND `create_time`='2024-10-22 00:00:00' AND `last_login_time`='2024-10-22 12:00:00' LIMIT 1;
2.10、执行恢复
-- 执行insert语句即可.
mysql> INSERT INTO `fruitsDB`.`employee` (`id`,`dept`,`age`,`name`,`create_time`,`last_login_time`) VALUES (1,1,25,'leo','2024-10-22 00:00:00','2024-10-22 12:00:00');
mysql> select * from employee;
3、方案总结
方案中展示了Binlog2sql回滚DML语句,但对于DDL语句却无法进行回滚,所以truncate和drop误删的数据需要使用其它方法恢复.
参考网址:https://mp.weixin.qq.com/s/o4rr1hkA9vUdMPZazmuvOQ