一、誤刪數(shù)據(jù)的情況:
- 使用delete語句誤刪數(shù)據(jù)行;
- 使用drop table或者truncate table語句誤刪數(shù)據(jù)表;
- 使用drop database語句誤刪數(shù)據(jù)庫;
- 使用rm命令誤刪整個(gè)MySQL實(shí)例。
二、各種誤刪數(shù)據(jù)的恢復(fù)方法:
1、誤刪行:
<1>、恢復(fù)方法:
??如果是使用delete語句誤刪了數(shù)據(jù)行,可以用Flashback工具通過閃回把數(shù)據(jù)恢復(fù)回來。Flashback恢復(fù)數(shù)據(jù)的原理,是修改binlog的內(nèi)容,拿回原庫重放。而能夠使用這個(gè)方案的前提是,需要確保binlog_format=row 和 binlog_row_image=FULL。
<2>、具體恢復(fù)數(shù)據(jù)時(shí),對(duì)單個(gè)事務(wù)做如下處理:
- 對(duì)于insert語句,對(duì)應(yīng)的binlog event類型是Write_rows event,把它改成Delete_rows event即可;
- 對(duì)于delete語句,將Delete_rows event改為Write_rows event;
- 如果是Update_rows的話,binlog里面記錄了數(shù)據(jù)行修改前和修改后的值,對(duì)調(diào)這兩行的位置即可。
<3>、預(yù)防方法:
?①、把sql_safe_updates參數(shù)設(shè)置為on。這樣一來,如果忘記在delete或者update語句中寫where條件,或者where條件里面沒有包含索引字段的話,這條語句的執(zhí)行就會(huì)報(bào)錯(cuò)。
?②、代碼上線前,必須經(jīng)過SQL審計(jì)。
注意:
?①、如果誤刪數(shù)據(jù)涉及到了多個(gè)事務(wù)的話,需要將事務(wù)的順序調(diào)過來再執(zhí)行。(A,B,C)—>(C,B,A)。
?②、建議直接在主庫上執(zhí)行恢復(fù)操作。恢復(fù)數(shù)據(jù)比較安全的做法,是恢復(fù)出一個(gè)備份,或者找一個(gè)從庫作為臨時(shí)庫,在這個(gè)臨時(shí)庫上執(zhí)行這些操作,然后再將確認(rèn)過的臨時(shí)庫的數(shù)據(jù),恢復(fù)回主庫。
2、誤刪庫/表:
<1>、恢復(fù)的前提條件:
??這種情況下,要想恢復(fù)數(shù)據(jù),就需要使用全量備份,加增量日志的方式了。這個(gè)方案要求線上有定期的全量備份,并且實(shí)時(shí)備份binlog。
<2>、恢復(fù)過程:
?①、取最近一次全量備份,假設(shè)這個(gè)庫是一天一備,上次備份是當(dāng)天0點(diǎn);
?②、用備份恢復(fù)出一個(gè)臨時(shí)庫;
?③、從日志備份里面,取出凌晨0點(diǎn)之后的日志;
?④、把這些日志,除了誤刪除數(shù)據(jù)的語句外,全部應(yīng)用到臨時(shí)庫。
<3>、恢復(fù)過程注意:
- 為了加速數(shù)據(jù)恢復(fù),如果這個(gè)臨時(shí)庫上有多個(gè)數(shù)據(jù)庫,可以在使用mysqlbinlog命令時(shí),加上一個(gè)–database參數(shù),用來指定誤刪表所在的庫。這樣就避免了在恢復(fù)數(shù)據(jù)時(shí)還要應(yīng)用其他庫日志的情況。
- 在應(yīng)用日志的時(shí)候,需要跳過誤操作的那個(gè)語句的binlog:
- 如果原實(shí)例沒有使用GTID模式,只能在應(yīng)用到包含誤操作的binlog文件的時(shí)候,先用–stop-position參數(shù)執(zhí)行到誤操作之前的日志,然后再用–start-position從誤操作之后的日志繼續(xù)執(zhí)行;
-
如果實(shí)例使用了GTID模式,假設(shè)誤操作命令的GTID是gtid1,那么只需要執(zhí)行
set gtid_next=gtid1; begin; commit;
先把這個(gè)GTID加到臨時(shí)實(shí)例的GTID集合,之后按順序執(zhí)行binlog的時(shí)候,就會(huì)自動(dòng)跳過誤操作的語句。
<4>、使用mysqlbinlog方法恢復(fù)數(shù)據(jù)還是不夠快的主要原因:
?①、如果是誤刪表,最好就是只恢復(fù)出這張表,也就是只重放這張表的操作,但是mysqlbinlog工具并不能指定只解析一個(gè)表的日志;
?②、用mysqlbinlog解析出日志應(yīng)用,應(yīng)用日志的過程就只能是單線程。
<5>、加快恢復(fù)數(shù)據(jù)速度的方法:
?(1)、在用備份恢復(fù)出臨時(shí)實(shí)例之后,將這個(gè)臨時(shí)實(shí)例設(shè)置成線上備庫的從庫:
?①、在start slave之前,先通過執(zhí)行;change replication filter replicate_do_table = (tbl_name)
命令,讓臨時(shí)庫只同步誤操作的表;
?②、這樣做也可以用上并行復(fù)制技術(shù),來加速整個(gè)數(shù)據(jù)恢復(fù)過程。
??binlog備份系統(tǒng)到線上備庫是一條虛線,是指如果由于時(shí)間太久,備庫上已經(jīng)刪除了臨時(shí)實(shí)例需要的binlog的話,可以從binlog備份系統(tǒng)中找到需要的binlog,再放回備庫中。操作方法:
?①、從備份系統(tǒng)下載備庫中缺少的文件,假設(shè)是master.000005和master.000006,放到備庫的日志目錄下;
?②、打開日志目錄下的master.index文件,在文件開頭加入兩行,內(nèi)容分別是 “./master.000005”和“./master.000006”;
?③、重啟備庫,目的是要讓備庫重新識(shí)別這兩個(gè)日志文件;
?④、現(xiàn)在這個(gè)備庫上就有了臨時(shí)庫需要的所有binlog了,建立主備關(guān)系,就可以正常同步了。
?(2)、延遲復(fù)制備庫:
??一般的主備復(fù)制結(jié)構(gòu)存在的問題是,如果主庫上有個(gè)表被誤刪了,這個(gè)命令很快也會(huì)被發(fā)給所有從庫,進(jìn)而導(dǎo)致所有從庫的數(shù)據(jù)表也都一起被誤刪了。延遲復(fù)制的備庫是一種特殊的備庫,通過 CHANGE MASTER TO MASTER_DELAY = N
命令,可以指定這個(gè)備庫持續(xù)保持跟主庫有N秒的延遲。
??比如把N設(shè)置為3600,這就代表了如果主庫上有數(shù)據(jù)被誤刪了,并且在1小時(shí)內(nèi)發(fā)現(xiàn)了這個(gè)誤操作命令,這個(gè)命令就還沒有在這個(gè)延遲復(fù)制的備庫執(zhí)行。這時(shí)候到這個(gè)備庫上執(zhí)行stop slave,再通過之前介紹的方法,跳過誤操作命令,就可以恢復(fù)出需要的數(shù)據(jù)。這樣的話,就隨時(shí)可以得到一個(gè)只需要最多再追1小時(shí),就可以恢復(fù)出數(shù)據(jù)的臨時(shí)實(shí)例,也就縮短了整個(gè)數(shù)據(jù)恢復(fù)需要的時(shí)間。
<6>、預(yù)防誤刪庫/表的方法:
- 賬號(hào)分離。這樣做的目的是,避免寫錯(cuò)命令。比如:
- 只給業(yè)務(wù)開發(fā)同學(xué)DML權(quán)限,而不給truncate/drop權(quán)限。而如果業(yè)務(wù)開發(fā)人員有DDL需求的話,也可以通過開發(fā)管理系統(tǒng)得到支持。
- 即使是DBA團(tuán)隊(duì)成員,日常也都規(guī)定只使用只讀賬號(hào),必要的時(shí)候才使用有更新權(quán)限的賬號(hào)。
- 制定操作規(guī)范。這樣做的目的,是避免寫錯(cuò)要?jiǎng)h除的表名。比如:
- 在刪除數(shù)據(jù)表之前,必須先對(duì)表做改名操作。然后,觀察一段時(shí)間,確保對(duì)業(yè)務(wù)無影響以后再刪除這張表。
- 改表名的時(shí)候,要求給表名加固定的后綴(比如加_to_be_deleted),然后刪除表的動(dòng)作必須通過管理系統(tǒng)執(zhí)行。并且,管理系刪除表的時(shí)候,只能刪除固定后綴的表。
3、rm刪除數(shù)據(jù):
??對(duì)于一個(gè)有高可用機(jī)制的MySQL集群來說,最不怕的就是rm刪除數(shù)據(jù)了。只要不是惡意地把整個(gè)集群刪除,而只是刪掉了其中某一個(gè)節(jié)點(diǎn)的數(shù)據(jù)的話,HA系統(tǒng)就會(huì)開始工作,選出一個(gè)新的主庫,從而保證整個(gè)集群的正常工作。這時(shí),要做的就是在這個(gè)節(jié)點(diǎn)上把數(shù)據(jù)恢復(fù)回來,再接入整個(gè)集群。當(dāng)然了,現(xiàn)在不止是DBA有自動(dòng)化系統(tǒng),SA(系統(tǒng)管理員)也有自動(dòng)化系統(tǒng),所以也許一個(gè)批量下線機(jī)器的操作,會(huì)讓整個(gè)MySQL集群的所有節(jié)點(diǎn)都全軍覆沒。應(yīng)對(duì)這種情況,只能是說盡量把備份跨機(jī)房,或者最好是跨城市保存。