工作中難免會誤刪數據,下面說一下怎樣從導出的備份數據和binlog日志中恢復數據。關於備份數據和binlog可以參考下面的文章:
一、恢復數據思路
總體思路是從備份文件中恢復已備份的數據,還有一些未備份的數據從binlog日志中恢復。當然,具體場景具體分析,否則沒有意義。如下:
場景1:知道誤刪了一張表中ID是5的數據,有該數據的備份,且備份后該數據沒有變過。此情況可以直接把備份的數據取出來,寫入到該表中。
場景2:刪除的數據沒有備份,在binlog日志中找到該記錄的所有操作,結合mysqlbinlog一步步分析執行,最終恢復該條數據。
從上面的兩種場景來看,恢復數據都要找到該條數據的初始數據(即備份的數據,或者binlog日志中寫入的數據),以及該條數據再后面是否經過變化。那么怎樣知道該條數據后面是否經過變化?除了對業務的熟練,我就知道這個點兒數據不會被修改,更准確的方法還是查binlog日志。
在實際中我們遇到的情況往往要比上面的場景復雜的多,比如我一不小心刪除了一部分數據,這部分數據有的備份了,有的沒有備份,並且數據量很大或者誤刪了表。這種情況比較復雜,下面演示一下這種情況下的數據恢復。
二、演示恢復數據
1、模擬數據操作
1)准備數據
CREATE DATABASE IF NOT EXISTS mydb1 DEFAULT CHARACTER SET utf8; USE mydb1; DROP TABLE IF EXISTS student; CREATE TABLE student ( id int(11) DEFAULT NULL, name varchar(20) DEFAULT NULL, age int(11) DEFAULT NULL, sex varchar(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO student VALUES ('1', 'a1', '18', '男'); INSERT INTO student VALUES ('2', 'a2', '16', '女'); INSERT INTO student VALUES ('3', 'a3', '17', '男'); INSERT INTO student VALUES ('4', 'a4', '17', '女'); INSERT INTO student VALUES ('5', 'a5', '18', '男'); INSERT INTO student VALUES ('6', 'a6', '19', '女');
2)數據備份
mysqldump -uroot -p123456 mydb1 > /var/mysql/backup/mydb1_$(date +%Y%m%d_%H%M%S).sql
3)執行正常操作
INSERT INTO student VALUES ('7', 'a7', '17', '女'); INSERT INTO student VALUES ('8', 'a8', '17', '男'); INSERT INTO student VALUES ('9', 'a9', '20', '女'); UPDATE student SET name='a33' WHERE id=3;
備份和當前的情況分別是:
4)執行誤刪除操作
DELETE FROM student WHERE age=17;
此時數據如下:
5)執行正常操作
INSERT INTO student VALUES ('10', 'a10', '18', '女');
INSERT INTO student VALUES ('11', 'a11', '17', '男');
最終數據如下 :
2、恢復數據分析
1)查找備份數據時的log日志文件,確定備份后,下一個次提交的偏移位置。
我的方法是先查找當前的日志文件,然后依次往前面的號的文件里找,直到發現與備份日期相近的日期為止。
當前的日志文件是2號文件,則先在2號文件中找日期與20200609_221029鄰近的記錄(備份日期是2020-06-09 22:10:29)
[root@localhost mysql]# mysqlbinlog --base64-output=decode-rows -v mysql-bin.000002;
可以看到,備份后,下一個次提交的偏移位置是8805。
2)查找誤刪語句提交開始的偏移位置
可以看到誤刪語句提交開始的偏移位置是9935
3)查找誤刪語句執行完之后的位置
可以看到誤刪語句執行完之后的位置是10262
4)執行導入備份sql語句,記住大致時間
mysql> source /var/mysql/backup/mydb1_20200609_221029.sql;
5)找到日志中開始導入備份sql的位置
可以看到開始導入備份sql的位置是10755
3、恢復數據
1)導入備份sql已經恢復了部分數據
2)恢復備份后到誤刪之前的數據,起始位置:8805到9935
mysqlbinlog --start-position=8805 --stop-position=9935 mysql-bin.000002 |mysql -uroot -p123456;
3)恢復執行完誤刪語句之后到執行備份sql之前的數據,起始位置10262到10755
mysqlbinlog --start-position=10262 --stop-position=10755 mysql-bin.000002 |mysql -uroot -p123456;
4)恢復完成,查看現在數據
5)驗證是否成功
備注:
1)本篇使用的MySQL版本是5.7.30,注意不同版本之間可能會有差異。
2)完成數據恢復以后最好再執行一下備份語句,避免以后從日志恢復的時候,日志中包含導入備份sql語句,語句比較龐大。
3)如果在導入備份sql的時候,在drop表之前,用戶操作了表,而執行drop表后,用戶操作信息被刪除,可能導致數據丟失。