誤刪數(shù)據包含如下四種情況
(2)使用 drop table 或者 truncate table 語句誤刪數(shù)據表;
(3)使用 drop database 語句誤刪數(shù)據庫;
(4)使用 rm 命令誤刪整個 MySQL 實例;
前面已經說了第一種情況使用 delete 命令刪除的數(shù)據,你還可以用 Flashback 來恢復。而使用 truncate /drop table 和 drop database 命令刪除的數(shù)據,就沒辦法通過 Flashback 來恢復了。
因為,即使我們配置了 binlog_format=row,執(zhí)行這三個命令時,記錄的 binlog 還是 statement 格式。binlog 里面就只有一個 truncate/drop 語句,這些信息是恢復不出數(shù)據的。
誤刪庫 / 表這種情況下,要想恢復數(shù)據,就需要使用全量備份,加增量日志的方式了。這個方案要求線上有定期的全量備份,并且實時備份 binlog。
恢復數(shù)據的流程如下:1.取最近一次全量備份恢復出一個臨時庫;
2.從binlog備份里面取出這次備份時間點之后的日志;
3.把日志除了誤刪數(shù)據的語句外,全部應用到臨時庫;
模擬恢復,假設每周日全備一次,之后每天進行增量備份一次
全備(周日)
innobackupex -ucjr -pcjr -H1.15.57.253 -P3306 --no-timestamp /backup/full &>/backup/xbk_full.log
模擬周一數(shù)據變化
create database cs charset utf8;
use cs ;
create table t1 (id int);
insert into t1 values(1),(2),(3);
第一次增量備份(周一)
innobackupex -ucjr -pcjr -H1.15.57.253 -P3306 --no-timestamp --incremental --incremental-basedir=/backup/full /backup/inc1 &>/backup/inc1.log
模擬周二數(shù)據
create table t2 (id int);insert into t2 values(1),(2),(3);
第二次增量備份(周二)
innobackupex -ucjr -pcjr -H1.15.57.253 -P3306 --no-timestamp --incremental --incremental-basedir=/backup/inc1 /backup/inc2 &>/backup/inc2.log
模擬周三數(shù)據變化
create table t3 (id int);
insert into t3 values(1),(2),(3);
drop database cs; 誤刪數(shù)據庫
恢復思路:
1. 檢查備份:周日full+周一inc1+周二inc2,周三的完整二進制日志
2. 進行備份整理,截取關鍵的二進制日志(從備份——誤刪除之前,將誤刪除的gitd排除出去)
3. 備份恢復到一個臨時庫,再用binlog日志恢復
(1) 全備的整理
innobackupex --apply-log --redo-only /backup/full
(2) 合并inc1到full中
innobackupex --apply-log --redo-only --incremental-dir=/backup/inc1 /backup/full
(3) 合并inc2到full中
innobackupex --apply-log --incremental-dir=/backup/inc2 /backup/full
(4) 最后一次整理全備
innobackupex --apply-log /data/backup/full
--redo-only參數(shù), 所有增量合并時(除了最后一次增量),防止LSN號對不上,因為--apply-log包含了前滾和回滾操作定位到binlog的gtid位置
mysqlbinlog --no-defaults --base64-output=decode-rows -v -v mysql-bin.000013 | awk 'BEGIN{IGNORECASE=1} {if($0~/drop/)count[$1" " $2" " $3" "$NF]++}END{for(i in count)print i,"\t",count[i]}'|column -t|sort -k3nr

在mysql-bin.000013中
# at 3160
#211124 14:32:38 server id 572533306 end_log_pos 3225 CRC32 0xea347e46 GTID last_committed=11 sequence_number=12 rbr_only=no
SET @@SESSION.GTID_NEXT= '671c995a-fc15-11eb-946a-525400dc7f2a:908'/*!*/;
# at 3225
#211124 14:32:38 server id 572533306 end_log_pos 3311 CRC32 0xc951897a Query thread_id=375 exec_time=0 error_code=0
SET TIMESTAMP=1637735558/*!*/;
SET @@session.pseudo_thread_id=375/*!*/;
drop database cs
/*!*/;
# at 3311恢復到臨時庫
1.創(chuàng)建數(shù)據目錄,拷貝數(shù)據文件
mkdir -p /data/mysql
cd /backup/full
cp -a * /data/mysql
2.編輯配置文件
cp /etc/my.cnf /etc/mytemp.cnf
vim /etc/mytemp.cnf
datadir=/data/mysql
3.賦權
chown mysql:mysql -R /data
4.啟動
mysqld_safe --defaults-file=/etc/mytemp.cnf --user=mysql &
已經恢復到周二為止數(shù)據

將誤操作的binlog的gitd排除掉,前面已經查詢得知該誤刪除的gtid
# at 3160
#211124 14:32:38 server id 572533306 end_log_pos 3225 CRC32 0xea347e46 GTID last_committed=11 sequence_number=12 rbr_only=no
SET @@SESSION.GTID_NEXT= '671c995a-fc15-11eb-946a-525400dc7f2a:908'/*!*/;
# at 3225
#211124 14:32:38 server id 572533306 end_log_pos 3311 CRC32 0xc951897a Query thread_id=375 exec_time=0 error_code=0
SET TIMESTAMP=1637735558/*!*/;
SET @@session.pseudo_thread_id=375/*!*/;
drop database cs
/*!*/;
# at 3311mysqlbinlog --skip-gtids --exclude-gtids='671c995a-fc15-11eb-946a-525400dc7f2a:908' /data/3306/binlog/mysql-bin.000013 >/backup/binlog.sql
登錄臨時庫,應用
source /backup/binlog.sql
查看已經恢復誤刪的庫,周三的更新也恢復了。

減少誤操作的建議
1、賬號分離,只給業(yè)務開發(fā)同學 DML 權限,而不給 truncate/drop 權限。而如果業(yè)務開發(fā)人員有 DDL 需求的話,也可以通過開發(fā)管理系統(tǒng)得到支持。
即使是 DBA 團隊成員,日常也都規(guī)定只使用只讀賬號,必要的時候才使用有更新權限的賬號。
2、制定操作規(guī)范。這樣做的目的,是避免寫錯要刪除的表名。
比如:在刪除數(shù)據表之前,必須先對表做改名操作。然后,觀察一段時間,確保對業(yè)務無影響以后再刪除這張表。改表名的時候,要求給表名加固定的后綴(比如加 _to_be_deleted),然后刪除表的動作必須通過管理系統(tǒng)執(zhí)行。并且,管理系刪除表的時候,只能刪除固定后綴的表。




