一、簡介
數據在當今的互聯網行業中非常重要,掌握了數據能夠從中發現價值,所以數據對於公司來書再重要不過了,當我們面臨數據的丟失時,比如數據意外刪除、自然災害等,然而數據的備份和恢復就顯得尤爲重要。
二、MySQL/MariaDB數據備份與恢復
常見的備份類型:
根據備份時數據庫是否在線:
冷備:cold backup,服務器離線,線上業務終止,無法執行讀寫操作,但是此方法備份數據最爲靠譜,丟數據少 熱備:hot backup,服務器在線,線上業務正常進行,讀寫操作都可進行,此方法備份要求複雜
溫備:warn backup,服務器在線,但是對數據庫施加全局鎖,只讀操作正常進行,不可寫
根據備份時的接口:
物理備份:physical backup,直接從數據庫的數據目錄進行cp複製歸檔的方式
邏輯備份:logical backup,把數據從庫中提取出來保存爲文本文件,主要用到的工具是mysqldump
注意:在數據量很大時使用邏輯備份很實用,當數據量小於10G時可以考慮使用mysqldump實現邏輯備份
根據備份的數據集:
完全備份:full backup,指的是備份整個庫
部分備份:partial backup,指的是備份數據庫中的部分數據
根據備份時是否備份整個 數據還是僅僅備份變化的數據
完全備份: full backup,備份整個數據庫
增量備份:incremental backup,僅僅備份上一次完全備份之後所改變的數據做備份的爲增量備份
差異備份:differential backup,比如說週一做一次備份,到週二了就把週一和週二這兩天的做一次備份,到週三就把週一週二週三的做一次備份,這就叫差異備份。比較容易恢復。
MYISAM與InnoDB區別:
MYISAM存儲引擎不支持熱備,而InnoDB支持 InnoDB記錄數據時都會給數據一個序列號,所以在備份時基於MVCC(多版本併發控制)的機制自動加快照,每啓動一個事務都會創建當前集的一個快照,而後基於MVCC的機制把每一個序列號都給它記錄一份下來,備份時只備份序列號或序列號之前的數據,往後發生的將不做備份,如果事務的隔離級別不是特別高的話,它並不會影響事務的讀寫操作,而這樣備份出來的數據一定是時間點一致的數據,所以要完成熱備份,通常是基於事務的存儲引擎才能夠完成的。
Innobase:提供了商業備份工具爲Innobackup,可以實現InnoDB的熱備支持增量備份;但是對於MyISAM不支持增量備份,只能實現完全備份,屬於物理備份,速度比較快。
Xtrabackup:由Percona組織提供的開源備份工具,物理備份,速度快;
mysqldump:常用的備份工具,也是個邏輯備份工具,用於小數據備份,一般都是在10G以下的小數據進行備份;可以使用文本進行二次處理;相當於MySQL的客戶端工具
三、數據備份與恢復實戰
常見備份工具:
mysqldump:邏輯備份工具,備份和恢復過程都比較慢
mysqldumper:多線程,的mysqldump,很難實現差異或增量備份
lvm-snapshot:
接近於熱備的工具,因爲要事先請求全局鎖,而後創建快照,並在創建快照完成後釋放全局鎖。使用cp,tar等工具進行物理備份;備份和恢復速度快,很難實現增量備份,並且請求全局需要一段時間,
邏輯備份工具,快於mysqldump
Innobase:商業備份工具,innobackup
xtrabackup:由percona提供的開源備份工具
innodb熱備,增量備份
myisam溫備,不支持增量
物理備份,速度快
mysqlhotcopy:幾乎冷備
mysqldump:僅適用於數據集較小的數據庫,數據量達到10G以上時建議不使用,備份太慢
mysqldump: mysqldump [options] [db_name [tbl_name ...]] mysqldump -uroot -hlocalhost -p testdb>/tmp/testdb.sql #備份單個表 mysql -uroot -hlocalhost -p testdb</tmp/testdb.sql #恢復時要事先創建數據庫 mysqldump -uroot -hlocalhost -p --databases db1 db2 db2 >/tmp/dbs.sql #使用此備份方法恢復時無需連入mysql創建數據庫 mysqldump -uroot -hlocalhost -p --all-databases >/tmp/all.sql #備份所有數據庫,適用於冷備 備份單庫或多庫:--databases 備份所有數據庫:--all-databases 注意:線上備份時,在實施溫備時需施加鎖對單表或多表施加鎖,讓用戶只能讀而不能寫 mysqldump -uroot -hlocalhost --databases testdb --lock-all-tables --flush-logs>/tmp/testdb.sql mysqldump -uroot -hlocalhost --databases testdb --single-transaction --flush-logs >/tmp/testdb1.sql #僅對Innodb存儲引擎實現熱備,不支持myisam引擎 mysqldump -uroot -hlocalhost --databases testdb --lock-all-tables --flush-logs --master-data=2 >/tmp/testdb2.sql mysqldump -uroot -hlocalhost --databases testdb --single-transaction --flush-logs --master-data=2 >/tmp/testdb3.sql --lock-all-tables #請求鎖定所有表之後備份 --single-transaction #能夠對innodb存儲引擎實現熱備 --flush-logs #備份時滾動日誌 --master-data=[0|1|2]設置爲1:保存爲一個change master語句 設置爲2:註釋掉的change master語句,設置爲0:不記錄 數據恢復:建議關閉二進制日誌,關閉其他用戶連接:set session sql_log_bin=0
使用mysqldump實現備份及其使用二進制日誌做恢復:
使用mysqldump實現備份,用二進制日誌恢復數據,這裏我們以當前系統上的數據庫hellodb爲例:
第一步:先把hellodb這個數據庫做一次完全備份,當數據庫的數據很大,比如說大於10G的話不建議使用mysqldump這個工具做備份,而使用物理備份更爲合理:
mysqldump -uroot -hlocalhost -p --databases hellodb --lock-all-tables --flush-logs --master-data=2 >/tmp/hellodb.sql
第二步:在數據庫hellodb中修改或創建一些表或數據,使得之前備份的數據跟現有的數據庫中的數據存在差別,以完後後面的通過二進制日誌進行數據恢復:
MariaDB [(none)]> use hellodb; Database changed MariaDB [hellodb]> show tables; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | scores | | students | | t1 | | teachers | | toc | +-------------------+ 8 rows in set (0.00 sec) MariaDB [hellodb]> drop table t1; Query OK, 0 rows affected (0.01 sec) MariaDB [hellodb]> create table tb1(id int,name varchar(20)); Query OK, 0 rows affected (0.02 sec) MariaDB [hellodb]> insert into tb1 values(1,'alren'),(2,'tbname'); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 MariaDB [hellodb]> show tables; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | scores | | students | | tb1 | | teachers | | toc | +-------------------+ 8 rows in set (0.00 sec) MariaDB [hellodb]> \q Bye
第三步:使用另外一臺服務器做恢復測試,將hellodb.sql,及發生改變的二進制日誌導入出來拷貝至另一臺主機
[root@centos6 binlog]# mysqlbinlog --start-position=245 master-bin.000005 /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; # at 4 #161117 6:43:00 server id 1 end_log_pos 245 Start: binlog v 4, server v5.5.32-MariaDB-log created 161117 6:43:00 # Warning: this binlog is either in use or was not closed properly. BINLOG ' 9OAsWA8BAAAA8QAAAPUAAAABAAQANS41LjMyLU1hcmlhREItbG9nAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAA2QAEGggAAAAICAgCAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAALfrHBw== '/*!*/; # at 245 #161117 7:01:18 server id 1 end_log_pos 352 Querythread_id=23exec_time=0error_code=0 use `hellodb`/*!*/; SET TIMESTAMP=1479337278/*!*/; SET @@session.pseudo_thread_id=23/*!*/; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/; SET @@session.sql_mode=0/*!*/; SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; /*!\C utf8 *//*!*/; SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/; SET @@session.lc_time_names=0/*!*/; SET @@session.collation_database=DEFAULT/*!*/; DROP TABLE `t1` /* generated by server */ /*!*/; # at 352 #161117 7:01:51 server id 1 end_log_pos 459 Querythread_id=23exec_time=0error_code=0 SET TIMESTAMP=1479337311/*!*/; create table tb1(id int,name varchar(20)) /*!*/; # at 459 #161117 7:02:43 server id 1 end_log_pos 530 Querythread_id=23exec_time=0error_code=0 SET TIMESTAMP=1479337363/*!*/; BEGIN /*!*/; # at 530 #161117 7:02:43 server id 1 end_log_pos 642 Querythread_id=23exec_time=0error_code=0 SET TIMESTAMP=1479337363/*!*/; insert into tb1 values(1,'alren'),(2,'tbname') /*!*/; # at 642 #161117 7:02:43 server id 1 end_log_pos 669 Xid = 1515 COMMIT/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; [root@centos6 binlog]# mysqlbinlog --start-position=245 master-bin.000005 >inre.sql
第四步:恢復數據,進入到mysql的命令行模式下或在命令行,把二進制日誌關掉,恢復數據時不需要把恢復信息記錄到二進制日誌中去;
MariaDB [(none)]>set sql_log_bin=0 MariaDB [hellodb]>source /root/hellodb1.sql MariaDB [hellodb]> source /root/inre.sql MariaDB [hellodb]>set sql_log_bin=1 MariaDB [hellodb]> show tables; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | scores | | students | | tb1 | | teachers | | toc | +-------------------+ 8 rows in set (0.00 sec)
如上訴結果說明數據已經恢復到原來最初始的狀態,基於mysqldump+二進制日誌的備份和恢復完成。