mysqldump全量備份+mysqlbinlog二進制日志增量備份


日常的數據備份及恢復測試,是DBA工作重中之重的事情,所以要做好備份及測試,日常的備份常見有mysqldump+binlog備份、xtrabackup+binlog備份,無論那一種,幾乎都少不了對binlog的備份,說明了binlog在數據恢復中的重要性,下面做個小測試,是工作中不少運維或者新人DBA容易犯的錯。


創建一個測試表tb1

復制代碼
<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 ~]# 

繼續模擬數據庫有寫入

這個時候是還是寫在mysql-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 |
+----------------------+-----------+
| mysql-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 |
+----------------------+-----------+
| mysql-bin.000001     | 589 | 
| mysql-bin.000002 | 321 |
+----------------------
+-----------+
2 rows in set (0.00 sec) <test>(root@localhost) [xuanzhi]>
復制代碼

上面我們進行flush logs是為了模擬現在已經有多個binlog文件了,恢復時進行多個binlog一起恢復

模擬誤操作

把xunazhi庫drop了:

復制代碼
<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,把備份導入

<test>(root@localhost) [(none)]> create database xuanzhi;    
Query OK, 1 row affected (0.00 sec)
[root@localhost ~]# mysql -uroot -p123456 xuanzhi <./xuanzhi.sql # 這個sql文件可以是絕對路徑也可以是相對路徑 
Warning: Using a password on the command line interface can be insecure.
[root@localhost ~]# 

查看數據

復制代碼
<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點:

復制代碼
[root@localhost ~]# mysqlbinlog -v --base64-output=DECODE-ROWS mysql-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 mysql-bin.000001 mysql-bin.000002 |mysql -uroot -p123456 xuanzhi 
# 這里的mysql-bin.000001和mysql-bin.000002等日志文件要從原來的位置拷貝出來,可以是絕對路徑也可以是相對路徑
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。大體過程是這樣的:

1、導入備份后,備份的所有操作都寫進最后一個binlog了,也就是上面的localhost-bin.000002

2、進行binlog恢復,從備份文件里的pos點開始,按理來說是可以恢復到最新數據的,但是上面導入了備份,導入時的所有操作都會記錄到localhost-bin.000002

3、備份導入時會有DROP TABLE和CREATE TABLE的動作寫進binlog里,所以最終得到的數據,還是備份時的數據。

 

 

總結:

        一、在恢復全備數據之前必須將該binlog文件移出,否則恢復過程中,會繼續寫入語句到binlog,最終導致增量恢復數據部分變得比較混亂

        二、做好數據文件及binlog的備份至關重要,但不是備份完就算了,要定期進行數據恢復測試或演練

        三、恢復時建議對外停止更新,即禁止更新數據庫


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM