MySQL的備份與恢復詳解

在公司中備份的策略並非千篇一概的,而是根據每一個企業 的實際生產環境與業務需求制定合適的備份策略。不管是選擇徹底備份仍是增量備份,都須要考慮它們的優缺點,是否適合當前的生產環境。同時爲了保證恢復的完整性,建議開啓二進制日誌功能,二進制日誌文件給恢復工做帶來了很大的靈活性,能夠基於時間點或位置進行恢復,考慮到數據庫性能,能夠將二進制日誌文件保存在其餘安全的硬盤中。mysql

在進行熱備時,備份操做和應用服務在同時運行,這樣十分消耗系統資源,致使數據庫服務性能降低,這就要求咱們選擇一個合適的時間(通常在應用負擔很小的時候)再來進行備份操做。sql

須要注意的是,不是備份就萬事大吉了,最好確認備份是否可用,因此備份以後的恢復測試是很是有必要的。同時備份時間也要靈活調整,如:數據庫

  1. 數據更新頻繁,則應該頻繁地備份。
  2. 數據的重要性,在有適當更新時進行備份。
  3. 在數據庫壓力小的時間段進行備份,如一週一次徹底備份,天天進行增量備份。
  4. 中小公司,徹底備份通常一天一次便可。
  5. 大公司可每週進行一次徹底備份,天天進行一次增量備份。
  6. 儘可能爲企業實現主從複製架構,以增長數據的可用性。

數據庫備份類型能夠從兩個角度來看待:vim

一、從物理與邏輯的角度:安全

物理備份是對數據庫操做系統的物理文件(如數據文件、日誌文件等)的備份。這種類型的備份適用於在出現問題時須要快速恢復的大型重要數據庫。架構

物理備份有能夠分爲如下幾種類型:ide

①、冷備份:在數據庫關閉狀態下進行備份操做;工具

②、熱備份:在數據庫處於運行狀態時進行備份操做,該備份方法依賴數據庫的日誌文件;性能

③、溫備份:數據庫鎖定表格(不可寫入,但可讀取)的狀態下進行備份;測試

邏輯備份是對數據庫邏輯組件(如表等數據庫對象)的備份,表示爲邏輯數據庫結構(create database、create table語句)和內容(insert語句或分隔文本文件)的信息。這種類型的備份使用於能夠編輯數據值或表結構較小的數據量,或者在不一樣的機器體系上從新建立數據。

二、從數據庫的備份策略角度:

從數據庫的備份策略角度,數據庫的備份可分爲徹底備份、差別備份和增量備份。其中呢,完整備份是實現差別、增量備份的基礎。

  1. 完整備份:每次對數據進行完整的備份,即對整個數據庫的備份。備份與恢復的操做很是簡單,可是數據存在大量的重複,會佔用大量的磁盤空間,備份的時間也很長。
  2. 差別備份:備份那些自從上次徹底備份以後被修改過的全部文件,備份的時間點是從上次完整備份起,備份數據會愈來愈大,恢復數據時,只需恢復上次的徹底備份和最近的一次差別備份。
  3. 增量備份:只有在那些在上次徹底備份或增量備份後被修改的文件纔會被備份,以上次完整備份或上次增量備份的時間爲時間點,僅僅備份這之間的數據變化,於是備份的數據量也小,佔用空間小,備份速度快,但恢復時,須要從上一次的完整備份開始到最後一次增量備份之間的全部增量依次恢復,一旦中間的數據發生損壞,將致使數據的丟失。

來幾個備份實例:

一、物理冷備份與恢復:

[root@localhost ~]# tar zcf /backup/mysql_$(date +%F).tar.gz /usr/local/mysql/data  #直接tar打包數據庫文件
[root@localhost ~]# cd /backup/
[root@localhost backup]# ls
mysql_2019-05-16.tar.gz              #備份後的文件
[root@localhost backup]#

二、mysqldump備份與恢復:

1)備份某一個表:

[root@localhost backup]# mysqldump -u root -p mysql user > mysql-user.sql          #備份mysql庫中的user表
Enter password:              #輸入密碼
[root@localhost backup]# ls                  #查看備份文件
mysql-user.sql

2)恢復mysql數據庫中的user表(注意路徑問題):

[root@localhost backup]# mysql -u root -p mysql < mysql-user.sql 
Enter password:

3)備份mysql庫:

[root@localhost backup]# mysqldump -u root -p --databases mysql > mysql.sql            #備份mysql庫
Enter password:              #輸入密碼
[root@localhost backup]# ls             #查看備份文件
mysql.sql

4)恢復mysql庫:

[root@localhost backup]# mysql -u root -p < mysql.sql 
Enter password:

5)備份全部的庫(當導出的數據量較大時,能夠添加「--opt」選項以優化執行速度):

[root@localhost backup]# mysqldump -u root -p --opt --all-databases > all-data.sql         #備份全部庫
Enter password:            #輸入密碼
[root@localhost backup]# ls              #查看備份文件
all-data.sql

三、MySQL增量備份與恢復:

與徹底備份不一樣,增量備份沒有重複數據,備分量不大,時間段,但其恢復比較麻煩,須要上次徹底備份及徹底備份以後的全部增量備份以後才能恢復,並且要對全部增量備份逐個反推恢復。MySQL沒有提供直接的增量備份辦法,因此通常是經過MySQL提供的二進制日誌來間接實現增量備份。

要進行MySQL的增量備份,那麼首先須要開啓二進制日誌功能:

[root@localhost ~]# mkdir /usr/local/mysql/logs      #建立專門存放二進制日誌文件的目錄
[root@localhost ~]# chown mysql:mysql /usr/local/mysql/logs           #更改目錄歸屬,使其擁有寫入權限
[root@localhost ~]# vim /etc/my.cnf        #編輯MySQL的主配文件
[mysqld]
log-bin=/usr/local/mysql/logs/mysql-bin            #寫入該行,指定二進制日誌的存放位置
[root@localhost ~]# systemctl restart mysqld             #重啓服務
[root@localhost ~]# ls -l /usr/local/mysql/logs                #而後便可看到目錄下自動生成的日誌文件
-rw-rw----. 1 mysql mysql 120 5月  16 14:16 mysql-bin.000001
-rw-rw----. 1 mysql mysql  39 5月  16 14:16 mysql-bin.index

如今全部對數據庫的修改,都將記錄mysql-bin.000001文件中,當執行「mysqladmin -u root -p flush-logs」刷新二進制日誌後,將會繼續生成一個名爲mysql-bin.000002的文件,以後全部的更改又將存在mysql-bin.000002文件中,以此類推.......

接下來對下面test庫中的user_info這個表進行備份:

mysql> select * from user_info;
+---------+----------+---------+
| gonghao | xingming | xingbie |
+---------+----------+---------+
|       1 | zhangsan | nan     |
|       2 | lisi     | nan     |
|       3 | wangwu   | nan     |
+---------+----------+---------+

1)先進行一次徹底備份:

[root@localhost ~]# mysqldump -u root -p test user_info >/backup/user_info_$(date +%F).sql;    #徹底備份
Enter password:                 #輸入密碼
[root@localhost ~]# ls /backup/              #查看備份生成的文件
user_info_2019-05-16.sql

2)刷新二進制文件:

[root@localhost ~]# mysqladmin -u root -p flush-logs             #刷新日誌文件
Enter password: 
[root@localhost ~]# ls -l /usr/local/mysql/logs/           查看,每次刷新後,都會多出一個日誌文件,
以後全部的修改,都將保存在這個日誌文件中
-rw-rw----. 1 mysql mysql 1007 5月  16 14:36 mysql-bin.000001
-rw-rw----. 1 mysql mysql  120 5月  16 14:36 mysql-bin.000002
-rw-rw----. 1 mysql mysql   78 5月  16 14:36 mysql-bin.index

3)如今數據庫中又多了兩條數據:

mysql> select * from user_info;
+---------+----------+---------+
| gonghao | xingming | xingbie |
+---------+----------+---------+
|       1 | zhangsan | nan     |
|       2 | lisi     | nan     |
|       3 | wangwu   | nan     |
|       4 | zhaoliu  | nan     |
|       5 | sunqi    | nan     |
+---------+----------+---------+

4)若是如今這個表被誤刪了,那麼能夠這樣恢復:

[root@localhost ~]# mysqladmin -u root -p flush-logs    #刷新日誌
Enter password: 

[root@localhost ~]# mysql -u root -p test < /backup/user_info_2019-05-16.sql          #先恢復徹底備份
Enter password: 
[root@localhost ~]# mysql -u root -p -e ' select * from test.user_info;'             #徹底備份的內容恢復成功
Enter password: 
+---------+----------+---------+
| gonghao | xingming | xingbie |
+---------+----------+---------+
|       1 | zhangsan | nan     |
|       2 | lisi     | nan     |
|       3 | wangwu   | nan     |
+---------+----------+---------+

在恢復增量備份時,--no-defaults選項必需要有,不然會報錯:

[root@localhost ~]# mysqlbinlog --no-defaults /usr/local/mysql/logs/mysql-bin.000002 | mysql -u root -p    #恢復增量備份
Enter password: 
[root@localhost ~]# mysql -u root -p -e ' select * from test.user_info;'         #查看是否恢復成功
Enter password: 
+---------+----------+---------+
| gonghao | xingming | xingbie |
+---------+----------+---------+
|       1 | zhangsan | nan     |
|       2 | lisi     | nan     |
|       3 | wangwu   | nan     |
|       4 | zhaoliu  | nan     |
|       5 | sunqi    | nan     |
+---------+----------+---------+

恢復成功了,那麼還有基於位置、時間的恢復,命令格式以下:

[root@localhost ~]# mysqlbinlog --no-defaults /usr/local/mysql/logs/mysql-bin.000002    #使用工具查看日誌文件

........................
# at 199       #199即爲一個動做的位置,接下來就是這個動做的時間
#190516 14:39:47 server id 1  end_log_pos 322 CRC32 0x5339b5bd  Query   thread_id=5 exec_time=0 error_code=0
use `test`/*!*/;
SET TIMESTAMP=1557988787/*!*/;
insert into user_info values('4','zhaoliu','nan')
/*!*/;
# at 322
#190516 14:39:47 server id 1  end_log_pos 353 CRC32 0x873df67e  Xid = 54
COMMIT/*!*/;               #該字樣表示爲提交
# at 353
#190516 14:39:57 server id 1  end_log_pos 432 CRC32 0xcd2543f7  Query   thread_id=5 exec_time=0 error_code=0
SET TIMESTAMP=1557988797/*!*/;
BEGIN
/*!*/;
# at 432
#190516 14:39:57 server id 1  end_log_pos 553 CRC32 0xc1300526  Query   thread_id=5 exec_time=0 error_code=0
SET TIMESTAMP=1557988797/*!*/;
insert into user_info values('5','sunqi','nan')
/*!*/;
# at 553
#190516 14:39:57 server id 1  end_log_pos 584 CRC32 0xebb496fb  Xid = 55
COMMIT/*!*/;

......................

[root@localhost ~]# mysqlbinlog --no-defaults --start-position='353' /usr/local/mysql/logs/mysql-bin.000002 | mysql -u root -p      
Enter password:

--start-position='353':表示爲從位置353開始恢復,該日誌文件353以前的數據不會恢復;

以上選項可更改成下面類型:

--stop-position='353':表示恢復到位置353就中止,該日誌文件353以後的數據不會恢復;

基於時間點的恢復:

--start-datetime='2019-05-16 14:39:47':表示恢復該時間以後的數據;

--stop-datetime='2019-05-16 14:39:47':表示僅恢復該時間以前的數據;

切記,全部類型的增量恢復以前,都必須先執行最近一次的徹底恢復。

相關文章
相關標籤/搜索