目前對MySQL比較流行的備份方式有兩種,一種上是使用自帶的mysqldump,另一種是xtrabackup,對於數據時大的環境,普遍使用了xtrabackup+binlog進行全量或者增量備份,那么如何快速的從xtrabackup備份中恢復單張表呢?從mysql 5.6版本開始,支持可移動表空間(Transportable Tablespace),利用這個功能也可以實現單表的恢復,下面進行從備份中恢復單張innodb表進行演練。
1. 針對InnoDB表恢復
2. 開啟了參數innodb_file_per_table
3. 安裝工具:mysql-utilities,其中mysqlfrm可以讀取表結構。
進行mysql-utilities安裝:
yum install mysql-utilities -y
創建一個測試,往里面插入數據后進行備份:
<test>(root@localhost) [xuanzhi]> show create table tb1\G *************************** 1. row *************************** Table: tb1 Create Table: CREATE TABLE `tb1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(10) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) <test>(root@localhost) [xuanzhi]> insert into tb1 (name) values ('aa'),('bb'),('cc'),('dd'); Query OK, 4 rows affected (0.00 sec) Records: 4 Duplicates: 0 Warnings: 0 <test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | | 3 | cc | | 4 | dd | +----+------+ 4 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
進行xtrabackup備份操作:
[root@localhost data]# innobackupex --defaults-file='/data/service/mysql-5.6.25/my.cnf' --user='root' --password='123456' --sock='/data/mysql-5.6/mysql.sock' /data
apply-log:
[root@localhost data]# innobackupex --defaults-file='/usr/local/mysql-5.6.25/my.cnf' --user='root' --password='123456' --sock='/data/mysql-5.6/mysql.sock' --apply-log /data/2017-03-24_09-40-54/
進行完整備份后,我們繼續往測試表tb1里插入數據,盡量模擬線上環境:
<test>(root@localhost) [xuanzhi]> insert into tb1 (name) values ('aa2'),('bb2'),('cc2'),('dd2'); Query OK, 4 rows affected (0.01 sec) Records: 4 Duplicates: 0 Warnings: 0 <test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | | 3 | cc | | 4 | dd | | 5 | aa2 | | 6 | bb2 | | 7 | cc2 | | 8 | dd2 | +----+------+ 8 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
xtrabackup備份里只有四條數據,備份后的數據,我們一會使用binlog來進行恢復。
進行誤操操作,把表drop了:
<test>(root@localhost) [xuanzhi]> drop table tb1; Query OK, 0 rows affected (0.21 sec) <test>(root@localhost) [xuanzhi]> show tables; Empty set (0.02 sec) <test>(root@localhost) [xuanzhi]>
使用mysqlfrm從備份中讀取表結構:
[root@localhost data]# mysqlfrm --diagnostic /data/2017-03-24_09-40-54/xuanzhi/tb1.frm # WARNING: Cannot generate character set or collation names without the --server option. # CAUTION: The diagnostic mode is a best-effort parse of the .frm file. As such, it may not identify all of the components of the table correctly. This is especially true for damaged files. It will also not read the default values for the columns and the resulting statement may not be syntactically correct. # Reading .frm file for /data/2017-03-24_09-40-54/xuanzhi/tb1.frm: # The .frm file is a TABLE. # CREATE TABLE Statement: CREATE TABLE `xuanzhi`.`tb1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(30) DEFAULT NULL, PRIMARY KEY `PRIMARY` (`id`) ) ENGINE=InnoDB; #...done. [root@localhost data]#
登錄數據庫進行建表:
<test>(root@localhost) [xuanzhi]> CREATE TABLE `xuanzhi`.`tb1` ( -> `id` int(11) NOT NULL AUTO_INCREMENT, -> `name` char(30) DEFAULT NULL, -> PRIMARY KEY `PRIMARY` (`id`) -> ) ENGINE=InnoDB; Query OK, 0 rows affected (0.05 sec) <test>(root@localhost) [xuanzhi]>
加一個寫鎖,確保安全:
<test>(root@localhost) [xuanzhi]> lock tables tb1 write; Query OK, 0 rows affected (0.00 sec) <test>(root@localhost) [xuanzhi]>
丟棄表空間:
<test>(root@localhost) [xuanzhi]> alter table tb1 discard tablespace; Query OK, 0 rows affected (0.01 sec)
從備份中拷貝ibd文件,並且修改權限:
[root@localhost data]# cp /data/2017-03-24_09-40-54/xuanzhi/tb1.ibd /data/mysql-5.6/xuanzhi/ [root@localhost data]# chown -R mysql:mysql /data/mysql-5.6/xuanzhi/tb1.ibd
載入表空間:
<test>(root@localhost) [xuanzhi]> alter table tb1 import tablespace; Query OK, 0 rows affected, 1 warning (0.04 sec) <test>(root@localhost) [xuanzhi]> show warnings; +---------+------+---------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+---------------------------------------------------------------------------------------------------------------------------------------------+ | Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './xuanzhi/tb1.cfg', will attempt to import without schema verification | +---------+------+---------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
有報一個warning,但不影響恢復,詳情可以看:https://yq.aliyun.com/articles/59271,我們查一下數據:
<test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | | 3 | cc | | 4 | dd | +----+------+ 4 rows in set (0.02 sec) <test>(root@localhost) [xuanzhi]>
可以看到備份的數據已經恢復了,但是備份后插入的數據明顯沒有出現,這個時候我們只能通過binlog進行恢復了,所以binlog的備份也是非常重要的。
我們查看一下備份時的pos點和binlog的文件名:
[root@localhost data]# cd /data/2017-03-24_09-40-54/ [root@localhost 2017-03-24_09-40-54]# cat xtrabackup_binlog_info mysql-bin.000002 1014
我們知道了備份后的起始POS點,還需要找出到誤操前的一個POS點進行恢復,找到drop table 前的POS點:
[root@localhost 2017-03-24_09-40-54]# mysqlbinlog -v --base64-output=DECODE-ROWS /data/mysql-5.6/mysql-bin.000002 | grep -C 10 -i "DROP" ### SET ### @1=8 ### @2='dd2' # at 1292 #170324 9:43:00 server id 1313306 end_log_pos 1323 CRC32 0x9f776b03 Xid = 198 COMMIT/*!*/; # at 1323 #170324 9:46:55 server id 1313306 end_log_pos 1445 CRC32 0x3fa6b448 Query thread_id=27 exec_time=0 error_code=0 use `xuanzhi`/*!*/; SET TIMESTAMP=1490320015/*!*/; DROP TABLE `tb1` /* generated by server */ /*!*/; # at 1445 #170324 9:51:52 server id 1313306 end_log_pos 1674 CRC32 0xdd5e1448 Query thread_id=27 exec_time=0 error_code=0 SET TIMESTAMP=1490320312/*!*/; CREATE TABLE `xuanzhi`.`tb1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` char(30) DEFAULT NULL, PRIMARY KEY `PRIMARY` (`id`) ) ENGINE=InnoDB /*!*/;
可以看到DROP TABLE 前的POS點是1323,那我們可以通過binlog2sql進行標准SQL的生成,binlog2sql的使用的和安裝請看之前我寫的博客:http://www.cnblogs.com/xuanzhi201111/p/6602489.html,再次為開源數據閃回工具的大神們點贊。
[root@localhost binlog2sql]# python binlog2sql.py -uroot -p123456 -dxuanzhi -ttb1 --start-position=1014 --stop-position=1323 --start-file='mysql-bin.000002' > recovery_tb1.sql
[root@localhost binlog2sql]# cat recovery_tb1.sql FLUSH ENGINE LOGS; INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (5, 'aa2'); #start 1094 end 1292 time 2017-03-24 09:43:00 INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (6, 'bb2'); #start 1094 end 1292 time 2017-03-24 09:43:00 INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (7, 'cc2'); #start 1094 end 1292 time 2017-03-24 09:43:00 INSERT INTO `xuanzhi`.`tb1`(`id`, `name`) VALUES (8, 'dd2'); #start 1094 end 1292 time 2017-03-24 09:43:00 [root@pm2 binlog2sql]#
把這sql文件進入導入即可進行備份后的數據恢復,導入數據前先進行解鎖:
<test>(root@localhost) [xuanzhi]> unlock tables; Query OK, 0 rows affected (0.01 sec)
[root@localhost binlog2sql]# mysql -uroot -p123456 <./recovery_tb1.sql
Warning: Using a password on the command line interface can be insecure.
[root@localhost binlog2sql]#
查看數據:
test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | | 3 | cc | | 4 | dd | | 5 | aa2 | | 6 | bb2 | | 7 | cc2 | | 8 | dd2 | +----+------+ 8 rows in set (0.02 sec) <test>(root@localhost) [xuanzhi]>
可以看到數據成功的恢復了,大家可以多加測試。
參考文章:
https://yq.aliyun.com/articles/59271
http://www.cnblogs.com/gomysql/p/6600616.html
作者:陸炫志 出處:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111 您的支持是對博主最大的鼓勵,感謝您的認真閱讀。本文版權歸作者所有,歡迎轉載,但請保留該聲明。 |