MySQL恢復誤刪數據解決方案


  工作中難免會誤刪數據,下面說一下怎樣從導出的備份數據和binlog日志中恢復數據。關於備份數據和binlog可以參考下面的文章:

  MySQL導入、導出、數據庫定時備份

  MySQL5.7開啟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表后,用戶操作信息被刪除,可能導致數據丟失。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM