目錄
- 誤刪行
- 事前預防誤刪行數據方法
- 誤刪表/庫
- 延遲復制備庫
- 事前預防誤刪庫/表方法
傳統的架構不能預防誤刪數據,因為主庫的一個drop table命令,會通過binlog傳給所有從庫和級聯從庫,進而導致整個集群的實例都會執行這個命令。
MySQL相關的誤刪除數據分類:
1、使用delete語句誤刪數據行
2、使用drop table 或者 truncate table 語句誤刪數據表
3、使用drop database語句誤刪數據庫
4、使用rm命令誤刪整個MySQL實例
誤刪行
若使用delete語句誤刪數據行,可以用Flashback工具通過閃回把數據恢復。
原理:修改binlog內容,拿回原庫重放。
前提:binlog_fromat = row 和binlog_row_image = FULL
具體措施:
1、對于insert語句,對應的binlog event 類型為WrIte_rows event,將其改為Delete_rows event
2、同理,對于delete,將Delete_rows event 改為Write_rows event
3、對于Update_rows,binlog記錄了數據行修改前和修改后的值,對調兩行位置即可
如果誤操作是多個,如:
(A)delete ...
(B)insert ...
(C)update ...
若要恢復這三個事務之前狀態,用Flashback工具解析binlog后,寫回主庫:
(reverse C)update ...
(reverse B)delete ...
(reverse A)insert ...
恢復數據的比較安全的做法是恢復出一個備庫,或者找一個從庫作為臨時庫,在這個臨時庫上執行這個操作,然后再將確認過的臨時庫的數據,恢復回主庫。
這是由于發現數據問題時間比較晚,導致會有在誤操作的基礎上的邏輯,如果單獨恢復這個幾行數據,會對數據造成二次破壞。
事前預防誤刪行數據方法
1、把sql_safe_updates
參數設置為on。這樣如果忘記在delete或者update語句中寫where條件,或者where條件里沒有包含索引字段,語句執行報錯
2、代碼上線前,必須經過SQL審計
誤刪表/庫
需要刪除一個表時,delete全表很慢,需要生成回滾日志、寫redo、寫binlog,所以常常使用truncate table 或者 drop table。
直接drop表和delete每行的最大區別就是,binlog對delete有詳細的刪除行內容,可是drop表后binlog就只有一個drop語句,恢復不了數據。
使用truncate/drop誤刪除數據時的恢復方法 :使用全量備份,加增量日志。要求對線上有定期的全量備份,并且實時備份binlog。
如果中午誤刪了庫,恢復數據流程如下:
1、取最近一次全量備份,假設這個庫是一天一備,上次備份是當天0點
2、用備份恢復出一個臨時庫
3、從日志被分離,取出0點之后的日志
4、把這些日志,除了誤刪除的數據的語句外,全部應用到臨時庫
加速恢復數據
1、如果臨時庫有多個數據庫,可以指定誤刪表所在的庫,這樣就避免了恢復數據時還要應用其他庫日志。
2、應用日志時,跳過誤操作的語句
不過這樣使用mysqlbinlog方法恢復數據不夠快。
mysqlbinlog恢復數據不夠快的原因:不能指定特定數據表、單線程操作
另外的加速方法
在用備份恢復出臨時實例之后,將這個臨時實例設置成線上備庫的從庫。
具體流程:
1、在start slave 之前,執行change replication filter replicate_do_table = (tbl_name)
,讓臨時庫只同步誤操作的表
2、可以使用并行復制技術,加速數據恢復
延遲復制備庫
如果一個庫備份很大,或者誤操作的時間舉例上一個全備份的時間較長,可以搭建延遲復制的備庫縮短恢復數據恢復需要的時間。
一般的主備復制結構存在問題:如果主庫有個表被誤刪了,這個命令很快也會被發給所有從庫,進而導致所有從庫的數據表也都一起被誤刪。
可以主動加大同步延遲,通過CHANGE MASTER TO MASTER_DELAY = N
命令,指定這個備庫始終與主庫有N秒延遲。如果把N設置為3600,代表如果主庫上有數據被誤刪了,并且在1h之內發現了這個誤操作,該命令此時沒有在延遲復制的備庫執行,所以可以到備庫上stop slave,然后跳過誤操作命令,恢復數據。
事前預防誤刪庫/表方法
1、賬號分離。
只給業務開發人員DML權限,不給truncate/drop權限。
DBA團隊成員,也只使用只讀賬號,必要時使用有更新權限的賬號
2、指定操作規范,避免寫錯要刪除的表名。
在刪除數據表之前,對表進行改名操作,并觀察一段時間,若對業務無影響,則刪除
改表名時要給表名加固定的后綴如_to_be_deleted
,然后刪除表的動作必須通過管理系統執行。并且管理系統只能刪除固定后綴的表。