數據庫在信息系統中擔任着很是重要的角色,尤爲一些對數據可靠性要求很是高的行業,若是發生宕機或數據丟失,其損失是很是嚴重的。
在公司中備份的策略並非千篇一概的,而是根據每一個企業 的實際生產環境與業務需求制定合適的備份策略。不管是選擇徹底備份仍是增量備份,都須要考慮它們的優缺點,是否適合當前的生產環境。同時爲了保證恢復的完整性,建議開啓二進制日誌功能,二進制日誌文件給恢復工做帶來了很大的靈活性,能夠基於時間點或位置進行恢復,考慮到數據庫性能,能夠將二進制日誌文件保存在其餘安全的硬盤中。mysql
在進行熱備時,備份操做和應用服務在同時運行,這樣十分消耗系統資源,致使數據庫服務性能降低,這就要求咱們選擇一個合適的時間(通常在應用負擔很小的時候)再來進行備份操做。sql
須要注意的是,不是備份就萬事大吉了,最好確認備份是否可用,因此備份以後的恢復測試是很是有必要的。同時備份時間也要靈活調整,如:數據庫
數據更新頻繁,則應該頻繁地備份。
數據的重要性,在有適當更新時進行備份。
在數據庫壓力小的時間段進行備份,如一週一次徹底備份,天天進行增量備份。
中小公司,徹底備份通常一天一次便可。
大公司可每週進行一次徹底備份,天天進行一次增量備份。
儘可能爲企業實現主從複製架構,以增長數據的可用性。
數據庫備份類型能夠從兩個角度來看待:vim
一、從物理與邏輯的角度:安全
物理備份是對數據庫操做系統的物理文件(如數據文件、日誌文件等)的備份。這種類型的備份適用於在出現問題時須要快速恢復的大型重要數據庫。架構
物理備份有能夠分爲如下幾種類型:ide
①、冷備份:在數據庫關閉狀態下進行備份操做;性能
②、熱備份:在數據庫處於運行狀態時進行備份操做,該備份方法依賴數據庫的日誌文件;測試
③、溫備份:數據庫鎖定表格(不可寫入,但可讀取)的狀態下進行備份;優化
邏輯備份是對數據庫邏輯組件(如表等數據庫對象)的備份,表示爲邏輯數據庫結構(create database、create table語句)和內容(insert語句或分隔文本文件)的信息。這種類型的備份使用於能夠編輯數據值或表結構較小的數據量,或者在不一樣的機器體系上從新建立數據。
二、從數據庫的備份策略角度:
從數據庫的備份策略角度,數據庫的備份可分爲徹底備份、差別備份和增量備份。其中呢,完整備份是實現差別、增量備份的基礎。
完整備份:每次對數據進行完整的備份,即對整個數據庫的備份。備份與恢復的操做很是簡單,可是數據存在大量的重複,會佔用大量的磁盤空間,備份的時間也很長。
差別備份:備份那些自從上次徹底備份以後被修改過的全部文件,備份的時間點是從上次完整備份起,備份數據會愈來愈大,恢復數據時,只需恢復上次的徹底備份和最近的一次差別備份。
增量備份:只有在那些在上次徹底備份或增量備份後被修改的文件纔會被備份,以上次完整備份或上次增量備份的時間爲時間點,僅僅備份這之間的數據變化,於是備份的數據量也小,佔用空間小,備份速度快,但恢復時,須要從上一次的完整備份開始到最後一次增量備份之間的全部增量依次恢復,一旦中間的數據發生損壞,將致使數據的丟失。
備份實例:
一、物理冷備份與恢復:
[root@mysql /]# systemctl stop mysqld #先停掉服務 [root@mysql /]# mkdir /backup # 建立一個備份目錄 [root@mysql /]# tar zcf /backup/mysql_all-$(date +%F).tar.gz /usr/local/mysql/data/ # 將整個數據庫文件夾打包備份,(date +%F)當前日期 [root@mysql /]# ls -l /backup/ # 查看備份文件 total 732 # 總用量 -rw-r--r-- 1 root root 746839 Aug 2 14:48 mysql_all-2019-08-02.tar.gz # 備份文件
來模擬數據庫文件丟失:
[root@mysql /]# mkdir /diushi [root@mysql /]# mv /usr/local/mysql/data/ /diushi/ # 將數據庫存放目錄移動到另外一個目錄
恢復數據庫:
[root@mysql /]# mkdir /restore/ [root@mysql /]# tar zxf /backup/mysql_all-2019-08-02.tar.gz -C /restore/ # 要先將備份文件釋放到一個空目錄中,而後將須要的恢復到原位置 [root@mysql /]# mv /restore/usr/local/mysql/data/ /usr/local/mysql/ # 將數據庫目錄恢復到原位置 [root@mysql /]# systemctl restart mysqld # 重啓服務驗證
二、mysqldump 備份與恢復:
備份數據庫
備份指定庫中的表:
mysqldump [選項] 庫名 表名 表名2 …… > /備份路徑/備份文件名 [root@mysql /]# mysqldump -u root -p test user > /backup/user-table.sql # 將test庫中的user表備份到backup目錄中 Enter password: # 輸入密碼
備份一個或多個完整的庫:
mysqldump [選項] --databases 庫名1 庫名2 …… > /備份路徑/備份文件名 [root@mysql /]# mysqldump -u root -p --databases test mysql > /backup/databases.sql # 將 test 和 mysql 庫備份到backup中 Enter password: # 輸入密碼
備份 MySQL 中的全部庫:
mysqldump [選項] --all-databases > /備份路徑/備份文件名 [root@mysql /]# mysqldump -u root -p --opt --all-databases > all-data.sql # --opt:優化執行速度 Enter password: # 輸入密碼
[root@mysql /]# ls backup/ # 查看備份文件 all-data.sql databases.sql user-table.sql
恢復數據庫:
恢復庫中的表
mysql [選項] 庫名 < /備份路徑/備份文件名 [root@mysql /]# mysql -u root -p test < /backup/user-table.sql Enter password: [root@mysql /]# mysql -u root -p -e ' show tables from test;' // 驗證導入結果 Enter password: +----------------+ | Tables_in_test | +----------------+ | user | +----------------+
恢復單個或多個庫:
[root@mysql /]# mysql -u root -p -e ' drop database test;' // 刪除 test 數據庫,模擬故障 Enter password: [root@mysql /]# mysql -u root -p -e ' show databases;' // 驗證 test 數據庫是否存在 Enter password: +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+ [root@mysql /]# mysql -u root -p < /backup/databases.sql // 執行導入恢復操做 Enter password: [root@mysql /]# mysql -u root -p -e ' show databases;' // 確認恢復後結果 Enter password: +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+
MySQL 增量備份與恢復:
與徹底備份不一樣,增量備份沒有重複數據,備分量不大,時間段,但其恢復比較麻煩,須要上次徹底備份及徹底備份以後的全部增量備份以後才能恢復,並且要對全部增量備份逐個反推恢復。MySQL沒有提供直接的增量備份辦法,因此通常是經過MySQL提供的二進制日誌來間接實現增量備份。
要進行MySQL的增量備份,首先須要開啓二進制日誌功能:
[root@mysql /]# mkdir /usr/local/mysql/logs # 建立一個存放二進制日誌文件的目錄 [root@mysql /]# cd /usr/local/mysql/ [root@mysql mysql]# chown mysql:mysql logs/ # 設置目錄歸屬,使其可以寫入 [root@mysql /]# vim /etc/my.cnf # 編寫配置文件 [mysqld] log-bin=/usr/local/mysql/logs/mysql-bin [root@mysql /]# systemctl restart mysqld # 重啓服務,使配置生效 [root@mysql /]# ll /usr/local/mysql/logs/mysql-bin.* # 目錄下自動生成日誌文件 -rw-rw---- 1 mysql mysql 120 Aug 2 17:04 /usr/local/mysql/logs/mysql-bin.000001 -rw-rw---- 1 mysql mysql 39 Aug 2 17:04 /usr/local/mysql/logs/mysql-bin.index
如今全部對數據庫的修改,都將記錄mysql-bin.000001文件中,當執行「mysqladmin -u root -p flush-logs」刷新二進制日誌後,將會繼續生成一個名爲mysql-bin.000002的文件,以後全部的更改又將存在mysql-bin.000002文件中,以此類推,每刷新一次,就會生成一個新文件!
首先咱們在表中先錄入一些信息,而後進行一次完整備份:
mysql> select * from user_info; +------+----------+----------+ | id | xingming | nianling | +------+----------+----------+ | 001 | zhangsan | 20 | | 002 | lisi | 25 | | 003 | wangwu | 20 | +------+----------+----------+
[root@mysql /]# mkdir /mysql_bak # 建立一個備份存放位置 [root@mysql /]# mysqldump -u root -p test user_info > /mysql_bak/test_userinfo$(date +%F).sql # 進行完整備份 Enter password: [root@mysql /]# ls /mysql_bak/ # 驗證備份結果 test_userinfo2019-08-02.sql [root@mysql /]# mysqladmin -u root -p flush-logs # 刷新日誌文件 Enter password: [root@mysql /]# ll /usr/local/mysql/logs/mysql-bin.* # 生成新的日誌文件000002 -rw-rw---- 1 mysql mysql 1192 Aug 2 17:18 /usr/local/mysql/logs/mysql-bin.000001 -rw-rw---- 1 mysql mysql 120 Aug 2 17:18 /usr/local/mysql/logs/mysql-bin.000002 -rw-rw---- 1 mysql mysql 78 Aug 2 17:18 /usr/local/mysql/logs/mysql-bin.index
繼續錄入新的數據,並進行增量備份:
mysql> select * from user_info; +------+----------+----------+ | id | xingming | nianling | +------+----------+----------+ | 001 | zhangsan | 20 | | 002 | lisi | 25 | | 003 | wangwu | 20 | | 004 | zhaoliu | 20 | | 005 | sunqi | 30 | +------+----------+----------+
[root@mysql /]# mysqladmin -u root -p flush-logs # 刷新日誌文件,這樣在000002中只有兩條數據的操做 Enter password: [root@mysql /]# cp /usr/local/mysql/logs/mysql-bin.000002 /mysql_bak/ # 將日誌文件複製到備份目錄中
模擬user_info 這個表被誤刪除了,恢復:
[root@mysql /]# mysql -u root -p test < /mysql_bak/test_userinfo2019-08-02.sql # 先恢復完整備份 Enter password: [root@mysql /]# mysql -u root -p -e ' select * from test.user_info;' # 查看一下確認,恢復成功 Enter password: +------+----------+----------+ | id | xingming | nianling | +------+----------+----------+ | 001 | zhangsan | 20 | | 002 | lisi | 25 | | 003 | wangwu | 20 | +------+----------+----------+ [root@mysql /]# mysqlbinlog --no-defaults /mysql_bak/mysql-bin.000002 | mysql -u root -p # 恢復增量備份,--no-defaults 選項必需要有 [root@mysql /]# mysql -u root -p -e ' select * from test.user_info;' # 確認,增量備份恢復成功 Enter password: +------+----------+----------+ | id | xingming | nianling | +------+----------+----------+ | 001 | zhangsan | 20 | | 002 | lisi | 25 | | 003 | wangwu | 20 | | 004 | zhaoliu | 20 | | 005 | sunqi | 30 | +------+----------+----------+
下來就是基於位置恢復和基於時間點恢復了,這兩種恢復是有很大的相同之處的,想要實現,必需先查看二進制日誌文件來確認恢復的位置或時間點。
[root@mysql /]# mysqlbinlog --no-defaults /mysql_bak/mysql-bin.000002 …… // 省略部份內容 #at 199 # 這一行就是操做ID號了 #190802 17:21:40 server id 1 end_log_pos 346 CRC32 0xc61c38c9 Query thread_id=4 exec_time=0 error_code=0 use `test`/*!*/; SET TIMESTAMP=1564737700/*!*/; insert into user_info (id,xingming,nianling) values('004','zhaoliu','20') /*!*/; #at 346 #190802 17:21:40 server id 1 end_log_pos 377 CRC32 0xea2c7707 Xid = 50 COMMIT/*!*/; # 操做確認標記 謹記一條操做在此纔算結束 #at 377 #190802 17:22:09 server id 1 end_log_pos 456 CRC32 0x6265a2a6 Query thread_id=4 exec_time=0 error_code=0 SET TIMESTAMP=1564737729/*!*/; BEGIN /*!*/; #at 456 #190802 17:22:09 server id 1 end_log_pos 601 CRC32 0x3727aeb7 Query thread_id=4 exec_time=0 error_code=0 SET TIMESTAMP=1564737729/*!*/; insert into user_info (id,xingming,nianling) values('005','sunqi','30') /*!*/; #at 601 #190802 17:22:09 server id 1 end_log_pos 632 CRC32 0x17c4779a Xid = 51 COMMIT/*!*/; #at 632 #190802 17:24:05 server id 1 end_log_pos 679 CRC32 0x9c698f03 Rotate to mysql-bin.000003 pos: 4 DELIMITER ; #End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@mysql /]# mysqlbinlog --no-defaults --stop-position='456' /mysql_bak/mysql-bin.000002 | mysql -u root -p # 恢復操做ID‘456’ 以前的操做 Enter password:
--start-position='456':表示爲從操做456開始恢復,該日誌文件456以前的數據不會恢復;
以上選項可更改成下面類型:
--stop-position='456':表示恢復到操做456就中止,該日誌文件456以後的數據不會恢復;
基於時間點的恢復:
--start-datetime='2019-08-2 17:22:09':表示恢復該時間以後的數據;
--stop-datetime='2019-08-2 17:22:09':表示僅恢復該時間以前的數據;
謹記,全部類型的增量恢復以前,都必須先執行最近一次的徹底恢復。
謹記,全部類型的增量恢復以前,都必須先執行最近一次的徹底恢復。
謹記,全部類型的增量恢復以前,都必須先執行最近一次的徹底恢復。