3、恢復一個表
3.1 從 備份恢復一個表
假設要恢復的表是 .:
#?提取某個庫的所有數據
sed?-n?'/^--?Current?Database:?`mytest`/,/^--?Current?Database:/p'?backup.sql?>?backup_mytest.sql
#?從庫備份文件中提取建表語句
sed?-e'/./{H;$!d;}'?-e?'x;/CREATE?TABLE?`mytest`/!d;q'?backup_mytest.sql?>?mytest_table_create.sql
#?從庫備份文件中提取插入數據語句
grep?-i?'INSERT?INTO?`mytest`'?backup_mytest.sql?>?mytest_table_insert.sql
#?恢復表結構到?mytest?庫
mysql?-u?-p?mytest?
#?恢復表數據到?mytest.mytest?表
mysql?-u?-p?mytest??mytest_table_insert.sql
3.2 從 備份恢復一個表
假設 ./ 目錄為解壓后應用過日志的備份文件。
3.2.1 表
假設從備份文件中恢復表 .。從備份文件中找到 .frm, .MYD, .MYI 這 3 個文件,復制到對應的數據目錄中,并授權 進入 MySQL。檢查表情況:
chengqm-3306>>show?tables;
+------------------+
|?Tables_in_mytest?|
+------------------+
|?mytest???????????|
|?t_myisam?????????|
+------------------+
2?rows?in?set?(0.00?sec)
chengqm-3306>>check?table?t_myisam;
+-----------------+-------+----------+----------+
|?Table???????????|?Op????|?Msg_type?|?Msg_text?|
+-----------------+-------+----------+----------+
|?mytest.t_myisam?|?check?|?status???|?OK???????|
+-----------------+-------+----------+----------+
1?row?in?set?(0.00?sec)
3.2.2 表
假設從備份文件中恢復表 .,恢復前提是設置了 e = on:
注意:
4、跳過誤操作SQL
跳過誤操作 SQL 一般用于執行了無法閃回的操作比如 drop table\。
4.1 使用備份文件恢復跳過
4.1.1 不開啟 GTID
使用備份文件恢復的步驟和基于時間點恢復的操作差不多,區別在于多一個查找 操作。舉個例子,我這里建立了兩個表 a 和 b,每分鐘插入一條數據,然后做全量備份mysql 批量還原數據庫,再刪除表 b,現在要跳過這條 SQL。
刪除表 b 后的數據庫狀態:
chgnqm-3306>>show?tables;
+------------------+
|?Tables_in_mytest?|
+------------------+
|?a????????????????|
+------------------+
1?row?in?set?(0.00?sec)
1.找出備份時的日志位置
[mysql@mysql-test?~]$?head?-n?25?backup.sql?|?grep?'CHANGE?MASTER?TO?MASTER_LOG_FILE'
--?CHANGE?MASTER?TO?MASTER_LOG_FILE='mysql-bin.000034',?MASTER_LOG_POS=38414;
2.找出執行了 drop table 語句的 pos 位置
[mysql@mysql-test?mysql_test]$??mysqlbinlog?-vv?/data/mysql_log/mysql_test/mysql-bin.000034?|?grep?-i?-B?3?'drop?table?`b`';
#?at?120629
#190818?19:48:30?server?id?83??end_log_pos?120747?CRC32?0x6dd6ab2a?????Query????thread_id=29488????exec_time=0????error_code=0
SET?TIMESTAMP=1566128910/*!*/;
DROP?TABLE?`b`?/*?generated?by?server?*/
從結果中我們可以看到 drop 所在語句的開始位置是 ,結束位置是 。
3.從 中提取跳過這條語句的其他記錄
#?第一條的?start-position?為備份文件的?pos?位置,stop-position?為?drop?語句的開始位置
mysqlbinlog?-vv?--start-position=38414?--stop-position=120629?/data/mysql_log/mysql_test/mysql-bin.000034?>?backup_inc_1.sql
#?第二條的?start-position?為?drop?語句的結束位置
mysqlbinlog?-vv?--start-position=120747?/data/mysql_log/mysql_test/mysql-bin.000034?>?backup_inc_2.sql
4.恢復備份文件
[mysql@mysql-test?~]$?mysql?-S?/tmp/mysql.sock?
全量恢復后狀態:
chgnqm-3306>>show?tables;
+------------------+
|?Tables_in_mytest?|
+------------------+
|?a????????????????|
|?b????????????????|
+------------------+
2?rows?in?set?(0.00?sec)
chgnqm-3306>>select?count(*)?from?a;
+----------+
|?count(*)?|
+----------+
|???????71?|
+----------+
1?row?in?set?(0.00?sec)
5.恢復增量數據
[mysql@mysql-test?~]$?mysql?-S?/tmp/mysql.sock?[mysql@mysql-test?~]$?mysql?-S?/tmp/mysql.sock?
恢復后狀態,可以看到已經跳過了 drop 語句:
chgnqm-3306>>show?tables;
+------------------+
|?Tables_in_mytest?|
+------------------+
|?a????????????????|
|?b????????????????|
+------------------+
2?rows?in?set?(0.00?sec)
chgnqm-3306>>select?count(*)?from?a;
+----------+
|?count(*)?|
+----------+
|??????274?|
+----------+
1?row?in?set?(0.00?sec)
4.1.2 開啟 GTID
使用 GTID 可以直接跳過錯誤的 SQL:
SET?SESSION?GTID_NEXT='對應的?GTID?值';
BEGIN;?COMMIT;
SET?SESSION?GTID_NEXT?=?AUTOMATIC;
4.2 使用延遲庫跳過
4.2.1 不開啟 GTID
使用延遲庫恢復的關鍵操作在于 start slave until。我在測試環境搭建了兩個 MySQL 節點,節點二延遲600秒,新建 a,b 兩個表,每秒插入一條數據模擬業務數據插入。
localhost:3306?->?localhost:3307(delay?600)
當前節點二狀態:
chengqm-3307>>show?slave?status?\G;
...
??????????????????Master_Port:?3306
????????????????Connect_Retry:?60
??????????????Master_Log_File:?mysql-bin.000039
??????????Read_Master_Log_Pos:?15524
???????????????Relay_Log_File:?mysql-relay-bin.000002
????????????????Relay_Log_Pos:?22845
????????Relay_Master_Log_File:?mysql-bin.000038
?????????????Slave_IO_Running:?Yes
????????????Slave_SQL_Running:?Yes
...
????????Seconds_Behind_Master:?600
...
當前節點二表:
chengqm-3307>>show?tables;
+------------------+
|?Tables_in_mytest?|
+------------------+
|?a????????????????|
|?b????????????????|
+------------------+
在節點一刪除表 b:
chengqm-3306>>drop?table?b;
Query?OK,?0?rows?affected?(0.00?sec)
chengqm-3306>>show?tables;
+------------------+
|?Tables_in_mytest?|
+------------------+
|?a????????????????|
+------------------+
1?row?in?set?(0.00?sec)
接下來就是跳過這條 SQL 的操作步驟。
1.延遲庫停止同步
stop?slave;
2.找出執行了 drop table 語句的前一句的 pos 位置
[mysql@mysql-test?~]$?mysqlbinlog?-vv?/data/mysql_log/mysql_test/mysql-bin.000039?|?grep?-i?-B?10?'drop?table?`b`';
...
#?at?35134
#190819?11:40:25?server?id?83??end_log_pos?35199?CRC32?0x02771167?????Anonymous_GTID????last_committed=132????sequence_number=133????rbr_only=no
SET?@@SESSION.GTID_NEXT=?'ANONYMOUS'/*!*/;
#?at?35199
#190819?11:40:25?server?id?83??end_log_pos?35317?CRC32?0x50a018aa?????Query????thread_id=37155????exec_time=0????error_code=0
use?`mytest`/*!*/;
SET?TIMESTAMP=1566186025/*!*/;
DROP?TABLE?`b`?/*?generated?by?server?*/
從結果中我們可以看到 drop 所在語句的前一句開始位置是 35134,所以我們同步到 35134(這個可別選錯了)。
3.延遲庫同步到要跳過的 SQL 前一條
change?master?to?master_delay=0;
start?slave?until?master_log_file='mysql-bin.000039',master_log_pos=35134;
查看狀態看到已經同步到對應節點:
chengqm-3307>>show?slave?status?\G;
...
??????????????????Master_Port:?3306
????????????????Connect_Retry:?60
??????????????Master_Log_File:?mysql-bin.000039
??????????Read_Master_Log_Pos:?65792
...
?????????????Slave_IO_Running:?Yes
????????????Slave_SQL_Running:?No
??????????Exec_Master_Log_Pos:?35134
...
???????????????Until_Log_File:?mysql-bin.000039
????????????????Until_Log_Pos:?35134
4.跳過一條 SQL 后開始同步
set?global?sql_slave_skip_counter=1;
start?slave;
查看同步狀態,刪除表 b 的語句已經被跳過:
chengqm-3307>>show?slave?status?\G;
...
?????????????Slave_IO_Running:?Yes
????????????Slave_SQL_Running:?Yes
...
1?row?in?set?(0.00?sec)
chengqm-3307>>show?tables;
+------------------+
|?Tables_in_mytest?|
+------------------+
|?a????????????????|
|?b????????????????|
+------------------+
2?rows?in?set?(0.00?sec)
4.2.2 開啟 GTID
使用 GTID 跳過的步驟會簡單很多,只要執行一條和要跳過的 SQL 的 GTID 相同的事務就可以跳過了。
SET?SESSION?GTID_NEXT='對應的?GTID?值';
BEGIN;?COMMIT;
SET?SESSION?GTID_NEXT?=?AUTOMATIC;
閃回操作就是反向操作,比如執行了 from a where id=1,閃回就會執行對應的插入操作 into a (id,…) (1,…),用于誤操作數據,只對 DML 語句有效,且要求 格式設為 ROW。本章介紹兩個比較好用的開源工具。
5.1
是大眾點評開源的一款用于解析 的工具mysql 批量還原數據庫,可以用于生成閃回語句,項目地址 。
5.1.1 安裝
wget?https://github.com/danfengcao/binlog2sql/archive/master.zip?-O?binlog2sql.zip
unzip?binlog2sql.zip
cd?binlog2sql-master/
#?安裝依賴
pip?install?-r?requirements.txt
5.1.2 生成回滾SQL
python?binlog2sql/binlog2sql.py?--flashback?\
-h<host>?-P<port>?-u<user>?-p'<password>'?-d<dbname>?-t<table_name>\
--start-file='<binlog_file>'?\
--start-datetime='<start_time>'?\
--stop-datetime='<stop_time>'?>?./flashback.sql
python?binlog2sql/binlog2sql.py?--flashback?\
-h<host>?-P<port>?-u<user>?-p'<password>'?-d<dbname>?-t<table_name>?\
--start-file='<binlog_file>'?\
--start-position=<start_pos>?\
--stop-position=<stop_pos>?>?./flashback.sql
5.2
是由美團點評公司技術工程部開發維護的一個回滾 DML 操作的工具,項目鏈接 。
限制:
5.2.1 安裝
#?依賴(centos)
yum?install?gcc*??pkg-config?glib2?libgnomeui-devel?-y
#?下載文件
wget?https://github.com/Meituan-Dianping/MyFlash/archive/master.zip?-O?MyFlash.zip
unzip?MyFlash.zip
cd?MyFlash-master
#?編譯安裝
gcc?-w??`pkg-config?--cflags?--libs?glib-2.0`?source/binlogParseGlib.c??-o?binary/flashback
mv?binary?/usr/local/MyFlash
ln?-s?/usr/local/MyFlash/flashback?/usr/bin/flashback
5.2.2 使用
生成回滾語句:
flashback?--databaseNames=<dbname>?--binlogFileNames=<binlog_file>?--start-position=<start_pos>?--stop-position=<stop_pos>?
執行后會生成 . 文件,需要用 解析出來再使用:
mysqlbinlog?-vv?binlog_output_base.flashback?|?mysql?-u<user>?-p
關注我們
長按或掃描下面的二維碼關注Linux公社
關注Linux公社,添加“星標”
每天獲取技術干貨,讓我們一起成長
合作聯系:root@linuxidc.net