恢復MySQL數據到誤刪的表之前的數據

一、演示環境說明:

系統CentOS Linux release 7.2.1511 (Core) X_86 64位最小化安裝
mysql版本是官方二進制版本5.7.22-22,mysql採用的是二進制安裝,單機上開啓2個mysql實例,mysql實例要開啓定時器event_scheduler=ON. 而且2個mysql實例都要開啓Gtid
xtrabackup 採用的是rpm包安裝,版本是version 2.4.13

MySQL備份方式採用每天一次全量備份和binlog增量備份

二、模擬刪除庫,進行數據恢復演示:

提示:當然此處只是演示,嚴禁生成環境刪庫,刪表模擬,後果你懂得

故障模擬:
線上誤刪除一個testdb庫下的test1_event表,利用當天的mysql的全量備份+當天生成的mysql的binlog文件來恢復數據到誤刪的表test1_event之前的數據
恢復方式介紹:
官方推薦採用利用mysql binlog方式恢復,生產實踐驗證官方的這個方式已經是不嚴謹的做法了(下面的方法是官方推薦的)

故障恢復過程如下:
2.1接收到誤刪除之前,第一時間確認大概誤操作時間
2.2 登錄主庫查看當前的binlog位置點(要記住此時的binlog文件,後面恢復時會用到)

(root@'mgr01':mysql3306.sock)[testdb]>show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000005
         Position: 15211
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: bde7b592-b966-11e9-8c64-000c294f3e61:1-10445
1 row in set (0.00 sec)

2.3最好是flush logs下,讓接下來的sql寫入到新的binlog文件
2.4定位drop 表語句所在binglog文件的位置點:

[root@mgr01 binlog]#  mysqlbinlog -v --base64-output=decode-rows   /data/mysql/mysql3306/binlog/mysql-bin.000005|grep -i -C 15 drop
###   @1=10422
###   @2='tomcat'
###   @3='xiaohuahua'
###   @4='2019-08-08 14:22:18'
# at 14987
#190808 14:22:18 server id 63306  end_log_pos 15018 CRC32 0x873943dd    Xid = 20695
COMMIT/*!*/;
#at15018###################################
#190808 14:22:19 server id 63306  end_log_pos 15083 CRC32 0xcc8773ce    GTID    last_committed=34   sequence_number=35  rbr_only=no
SET @@SESSION.GTID_NEXT= 'bde7b592-b966-11e9-8c64-000c294f3e61:10445'/*!*/;
#at 15083
#190808 14:22:19 server id 63306  end_log_pos 15211 CRC32 0x8d445019    Query   thread_id=7213  exec_time=0 error_code=0
use `testdb`/*!*/;
SET TIMESTAMP=1565245339/*!*/;
SET @@session.sql_auto_is_null=0/*!*/;
DROP TABLE `test1_event` /* generated by server */
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
#End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

定位到15018 這個位置點就是利用binlog的文件恢復時的結束點

2.5恢復xtrabackup備份到 mysql3308 實例上:
提示:mysql 3308實例要開啓Gtid的

恢復備份的命令:

innobackupex --apply-log /data/backup/db_3306_20190808/
innobackupex  --defaults-file=/data/mysql/mysql3308/my3308.cnf --copy-back /data/backup/db_3306_20190808/

給數據目錄data mysql 權限:

 chown -R mysql.mysql /data/mysql/mysql3308/data/

啓動mysql3308 實例:

/usr/local/mysql/bin/mysqld --defaults-file=/data/mysql/mysql3308/my3308.cnf   &

查看到恢復到3308實例的數據,但是在備份3306庫到刪除表test1_event 這時間段還存在很多缺失的數據未找回,要從增量的binlog文件中找回:

| 10273 | tomcat   | xiaohuahua | 2019-08-08 14:17:16 |
| 10274 | tomcat   | xiaohuahua | 2019-08-08 14:17:18 |
+-------+----------+------------+---------------------+

(root@'mgr01':mysql3308.sock)[testdb]>select count(*) from test1_event;
+----------+
| count(*) |
+----------+
|    10273 |
+----------+
1 row in set (0.00 sec)

xtrabackup 備份是開啓Gtid的,所以下面使用mysqlbinlog命令 進行增量binglog文件恢復數據時,要添加參數--skip-gtids 忽略掉binlog文件的中的Gtid信息,要是不加參數--skip-gtids 進行恢復的話,導致數據恢復不到3308庫

正確的恢復命令如下:


mysqlbinlog    /data/mysql/mysql3306/binlog/mysql-bin.000001 --skip-gtids  |mysql -f --binary-mode  -S /tmp/mysql3308.sock 
mysqlbinlog    /data/mysql/mysql3306/binlog/mysql-bin.000002 --skip-gtids  |mysql -f --binary-mode  -S /tmp/mysql3308.sock 
mysqlbinlog    /data/mysql/mysql3306/binlog/mysql-bin.000003 --skip-gtids  |mysql -f --binary-mode  -S /tmp/mysql3308.sock 
mysqlbinlog    /data/mysql/mysql3306/binlog/mysql-bin.000004 --skip-gtids  |mysql -f --binary-mode  -S /tmp/mysql3308.sock 
mysqlbinlog    /data/mysql/mysql3306/binlog/mysql-bin.000005 --stop-position="15018"  --skip-gtids  |mysql -f --binary-mode  -S /tmp/mysql3308.sock 

參數說明:
--skip-gtids 忽略binlog文件中的Gtid的信息
--binary-mode 主要是爲了解決中文亂碼或者是特殊字符串亂碼的問題
-f 強制恢復,忽略報錯

執行完以上命令,數據就恢復到刪除表test1_event之前的了

下面的恢復命令會導致數據恢復不到mysql 3308 實例上:(原因是my3308實例開啓了Gtid參數導致的)


mysqlbinlog   /data/mysql/mysql3306/binlog/mysql-bin.000001 |mysql -f --binary-mode  -S /tmp/mysql3308.sock  
mysqlbinlog   /data/mysql/mysql3306/binlog/mysql-bin.000002 |mysql -f --binary-mode  -S /tmp/mysql3308.sock  
mysqlbinlog   /data/mysql/mysql3306/binlog/mysql-bin.000003 |mysql -f --binary-mode  -S /tmp/mysql3308.sock 
mysqlbinlog   /data/mysql/mysql3306/binlog/mysql-bin.000004 |mysql -f --binary-mode  -S /tmp/mysql3308.sock 
mysqlbinlog --stop-position="15018"  /data/mysql/mysql3306/binlog/mysql-bin.000005|mysql -f --binary-mode  -S /tmp/mysql3308.sock 

2.6如果新的實例mysql3308 啓動前從my3308.cnf中關閉掉Gtid參數:
3.
這樣的話採用mysqlbinlog /data/mysql/mysql3306/binlog/mysql-bin.00000* |mysql -f --binary-mode -S /tmp/mysql3308.sock 是可以將數據恢復到mysql 3308實例上的,但是恢復過程中報錯。這樣恢復到3308的數據,
生成的binlog文件是不記錄Gtid信息的


[root@mgr01 backup]# mysqlbinlog --stop-position="15018"  /data/mysql/mysql3306/binlog/mysql-bin.000005|mysql -f --binary-mode  -S /tmp/mysql3308.sock 
ERROR 1781 (HY000) at line 17: @@SESSION.GTID_NEXT cannot be set to UUID:NUMBER when @@GLOBAL.GTID_MODE = OFF.
ERROR 1781 (HY000) at line 50: @@SESSION.GTID_NEXT cannot be set to UUID:NUMBER when @@GLOBAL.GTID_MODE = OFF.
ERROR 1781 (HY000) at line 74: @@SESSION.GTID_NEXT cannot be set to UUID:NUMBER when @@GLOBAL.GTID_MODE = OFF.
ERROR 1781 (HY000) at line 98: @@SESSION.GTID_NEXT cannot be set to UUID:NUMBER when @@GLOBAL.GTID_MODE = OFF.

當然也可以採用下面的方式來恢復,同樣3308的實例的binglog文件是不記錄Gtid信息的,這種方法在恢復的過程中可能會出現報錯,不能完全保證數據的完整性和正確性,所以生產上最好不要使用這種方法來恢復找回數據

[root@mgr01 backup]# mysqlbinlog --skip-gtids  /data/mysql/mysql3306/binlog/mysql-bin.000001|mysql -f --binary-mode  -S /tmp/mysql3308.sock
ERROR 1050 (42S01) at line 27: Table 'test1_event' already exists
ERROR 1062 (23000) at line 92: Duplicate entry '1' for key 'PRIMARY'
ERROR 1537 (HY000) at line 132: Event 'e_test' already exists
mysqlbinlog --skip-gtids  /data/mysql/mysql3306/binlog/mysql-bin.000002|mysql -f --binary-mode  -S /tmp/mysql3308.sock
mysqlbinlog --skip-gtids  /data/mysql/mysql3306/binlog/mysql-bin.000003|mysql -f --binary-mode  -S /tmp/mysql3308.sock
mysqlbinlog --skip-gtids  /data/mysql/mysql3306/binlog/mysql-bin.000004|mysql -f --binary-mode  -S /tmp/mysql3308.sock
mysqlbinlog --skip-gtids --stop-position="15018" /data/mysql/mysql3306/binlog/mysql-bin.000005|mysql -f --binary-mode  -S /tmp/mysql3308.sock

友情提示:生產上還是最好開啓Gtid. 這樣在恢復數據和數據庫同步,以及解決同步錯誤是非常方便的

總結:

對於DDL語句像 drop database ,drop tables , drop tables , truncate table 這樣的語句就可以採用mysqlbinlog 來恢復。同時也可以採用binlog2sql工具來閃回

對於這樣的語句,不管binglog 格式爲row 格式,還是statement 格式,還是Mixed 格式,記錄的binlog格式都爲 statement 格式爲row
利用mysqlbinlog 只能支持到database級別的提取

全備+利用mysqlbinlog恢復到某個時間點
利用mysqlbinlog --skip-gtids 存在很大風險點

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章