平常的數據備份及恢復測試,是DBA工做重中之重的事情,因此要作好備份及測試,平常的備份常見有mysqldump+binlog備份、xtrabackup+binlog備份,不管那一種,幾乎都少不了對binlog的備份,說明了binlog在數據恢復中的重要性,下面作個小測試,是工做中很多運維或者新人DBA容易犯的錯。mysql
建立一個測試表tb1:sql
<test>(root@localhost) [xuanzhi]> show create table tb1\G *************************** 1. row *************************** Table: tb1 Create Table: CREATE TABLE `tb1` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` char(10) CHARACTER SET latin1 DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
往表裏插入兩條數據:數據庫
<test>(root@localhost) [xuanzhi]> insert into tb1 (name) value ('aa'),('bb'); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 <test>(root@localhost) [xuanzhi]> show master logs; +----------------------+-----------+ | Log_name | File_size | +----------------------+-----------+ | localhost-bin.000001 | 329 | +----------------------+-----------+ 1 row in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
這個時候對數據備份,若是是xtrabackup備份的話,會在有xtrabackup_binlog_info文件中記錄此時備份是到那個binlog文件和pos點的,若是是mysqldump備份,則須要帶上--master-data=2這個參數,下面咱們的數據量少,用mysqldump備份:運維
[root@localhost ~]# mysqldump -uroot -p123456 -R --events --triggers=true --master-data=2 --single-transaction xuanzhi > xuanzhi.sql Warning: Using a password on the command line interface can be insecure. [root@localhost ~]# grep -i "CHANGE MASTER" xuanzhi.sql -- CHANGE MASTER TO MASTER_LOG_FILE='localhost-bin.000001', MASTER_LOG_POS=329; [root@localhost ~]#
備份完後,繼續模擬數據庫有寫入,而仍是寫在localhost-bin.000001測試
<test>(root@localhost) [xuanzhi]> insert into tb1 (name) value ('cc'),('dd'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 <test>(root@localhost) [xuanzhi]> show master logs; +----------------------+-----------+ | Log_name | File_size | +----------------------+-----------+ | localhost-bin.000001 | 538 | +----------------------+-----------+ 1 row in set (0.00 sec) <test>(root@localhost) [xuanzhi]> flush logs; Query OK, 0 rows affected (0.01 sec) <test>(root@localhost) [xuanzhi]> insert into tb1 (name) value ('ee'); Query OK, 1 row affected (0.00 sec) <test>(root@localhost) [xuanzhi]> show master logs; +----------------------+-----------+ | Log_name | File_size | +----------------------+-----------+ | localhost-bin.000001 | 589 | | localhost-bin.000002 | 321 | +----------------------+-----------+ 2 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
上面咱們進行flush logs是爲了模擬如今已經有多個binlog文件了,恢復時進行多個binlog一塊兒恢復。spa
進行誤操,把xunazhi庫drop了:code
<test>(root@localhost) [xuanzhi]> drop database xuanzhi; Query OK, 1 row affected (0.02 sec) <test>(root@localhost) [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.00 sec) <test>(root@localhost) [(none)]>
建立數據xuanzhi,把備份導入:orm
<test>(root@localhost) [(none)]> create database xuanzhi; Query OK, 1 row affected (0.00 sec)
[root@localhost ~]# mysql -uroot -p123456 xuanzhi <./xuanzhi.sql
Warning: Using a password on the command line interface can be insecure.
[root@localhost ~]#
查看數據:server
<test>(root@localhost) [(none)]> use xuanzhi Database changed <test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | +----+------+ 2 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
能夠看到備份前的數據恢復了,咱們如今要結合Binlog來恢復,但前提要找出誤操做前的pos點,也就是drop database xuanzhi前的pos點:blog
[root@localhost ~]# mysqlbinlog -v --base64-output=DECODE-ROWS localhost-bin.000002 |grep -C 10 -i "drop database" ### INSERT INTO `xuanzhi`.`tb1` ### SET ### @1=5 ### @2='ee' # at 290 #170327 21:10:55 server id 1313306 end_log_pos 321 CRC32 0x825a2f99 Xid = 78 COMMIT/*!*/; # at 321 #170327 21:19:25 server id 1313306 end_log_pos 422 CRC32 0x8c139cac Query thread_id=2 exec_time=0 error_code=0 SET TIMESTAMP=1490620765/*!*/; drop database xuanzhi /*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; [root@localhost ~]# mysql -uroot -p123456 xuanzhi <./xuanzhi.sql Warning: Using a password on the command line interface can be insecure. [root@localhost ~]#
從上面能夠看到,誤操做前的pos點是321,那咱們如今經過binlog來進行數據恢復:
[root@localhost mysql-5.6]# mysqlbinlog --start-position=329 --stop-position=321 localhost-bin.000001 localhost-bin.000002 |mysql -uroot -p123456 xuanzhi Warning: Using a password on the command line interface can be insecure. [root@localhost mysql-5.6]#
--start-position是備份後記錄下的pos點, --stop-position是誤操前的pos點,若是批多個binlog文件,那麼start-position是第一個binlog文件的pos點,stop-position是最後一個binlog的pos點,下面咱們看下數據是否恢復回來了:
<test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | | 3 | cc | | 4 | dd | | 5 | ee | +----+------+ 5 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
這裏要提的是進行恢復前,要把須要恢復的binlog備份好,或者移動拷貝一份到另外一個目錄,由於進行數據導入時也會繼續寫binlog。假如你沒有誤操做的狀況下,就是想測試一下數據的恢復,不少人的操做是導入備份,再從備份裏記錄的binlog文件名和pos點進行binlog恢復,發現步驟都很完美,也沒報錯,恢復後就是隻有備份時的數據,沒有備份後的數據,下面測試一下給你們看:
<test>(root@localhost) [xuanzhi]> insert into tb1 (name) value ('aa'),('bb'); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 <test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | +----+------+ 2 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]> show master logs; +----------------------+-----------+ | Log_name | File_size | +----------------------+-----------+ | localhost-bin.000001 | 329 | +----------------------+-----------+ 1 row in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
進行備份操做:
[root@localhost ~]# mysqldump -uroot -p123456 -R --events --triggers=true --master-data=2 --single-transaction xuanzhi > xuanzhi.sql Warning: Using a password on the command line interface can be insecure. [root@localhost ~]# grep -i "change master" xuanzhi.sql -- CHANGE MASTER TO MASTER_LOG_FILE='localhost-bin.000001', MASTER_LOG_POS=329; [root@localhost ~]#
繼續寫localhost-bin.000001後進行flush logs生成新的binlog再繼續寫數據,這裏只是想模擬localhost-bin.000001寫滿了切localhost-bin.000002,結合多個binlog一塊兒恢復
<test>(root@localhost) [xuanzhi]> insert into tb1 (name) value ('cc'),('dd'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 <test>(root@localhost) [xuanzhi]> flush logs; Query OK, 0 rows affected (0.00 sec) <test>(root@localhost) [xuanzhi]> insert into tb1 (name) value ('dd'); Query OK, 1 row affected (0.01 sec) <test>(root@localhost) [xuanzhi]> show master logs; +----------------------+-----------+ | Log_name | File_size | +----------------------+-----------+ | localhost-bin.000001 | 589 | | localhost-bin.000002 | 321 | +----------------------+-----------+ 2 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
下面進行恢復測試,正常來講先把備份導入:
[root@localhost ~]# mysql -uroot -p123456 xuanzhi <./xuanzhi.sql
Warning: Using a password on the command line interface can be insecure.
[root@localhost ~]#
查看數據,只有備份的那兩條記錄:
<test>(root@localhost) [xuanzhi]> select * from tb1; +----+------+ | id | name | +----+------+ | 1 | aa | | 2 | bb | +----+------+ 2 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
那如今經過localhost-bin.000001,localhost-bin.000002來恢復後面那3條數據,那麼起始pos是那個呢,就是上面備份完後備份文件裏的那個pos,咱們進到binlog的存放路徑:
能夠看到備份後的數據是沒有恢復回來的。爲何呢?由於導入備份的時候,又開始寫binlog了,而你恢復時用的binlog也就是如今導入備份時正在寫的binlog。大致過程是這樣的:
一、導入備份後,備份的全部操做都寫進最後一個binlog了,也就是上面的localhost-bin.000002
二、進行binlog恢復,從備份文件裏的pos點開始,按理來講是能夠恢復到最新數據的,可是上面導入了備份,導入時的全部操做都會記錄到localhost-bin.000002
三、備份導入時會有DROP TABLE和CREATE TABLE的動做寫進binlog裏,因此最終獲得的數據,仍是備份時的數據。
總結:
1、在恢復全備數據以前必須將該binlog文件移出,不然恢復過程當中,會繼續寫入語句到binlog,最終致使增量恢復數據部分變得比較混亂
2、作好數據文件及binlog的備份相當重要,但不是備份完就算了,要按期進行數據恢復測試或演練
3、恢復時建議對外中止更新,即禁止更新數據庫
做者:陸炫志 出處:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111 您的支持是對博主最大的鼓勵,感謝您的認真閱讀。本文版權歸做者全部,歡迎轉載,但請保留該聲明。 |