MySQL備份策略


1 關於備份

1.1 為什么要備份

  • 災難恢復,數據庫在運行過程中,終會遇到各種各樣的問題: 硬件故障、Bug 導致數據損壞、由於服務器宕機或者其他原因造成的數據庫不可用。除此以外還有人為操作:DELETE 語句忘加條件、ALTER TABLE 執行錯表、DROP TABLE 執行錯表、黑客攻擊,即使這些問題你都還沒遇到,但是根據墨菲定律,總會有遇上的時候。
  • 回滾,由於某種Bug或系統被黑造成大量的損失,這個時候就需要回滾到某個狀態。常見的有區塊鏈交易所被黑然后回滾,游戲漏洞被利用然后整體回滾。
  • 審計,有時候有這樣的需求:需要知道某一個時間點的數據是怎么樣的,可能是年末審計,也可能是因為官司。
  • 測試,一個基本的測試需求是,定時拉取線上數據到測試環境,如果有備份,就可以非常方便地拉取數據。

1.2 有哪些備份方式

1.2.1 邏輯備份

邏輯備份是最常見的方式,在數據量比較少的時候很常用。

邏輯備份的優勢:

  • 備份恢復比較簡單,例如 mysqldump 就是 MySQL 自帶的備份工作,無需額外安裝。恢復的時候可以直接使用 mysql 命令進行恢復。
  • 可以遠程備份和恢復,也就是說,可以在其他機器執行備份命令。
  • 備份出來的數據非常直觀,備份出來后,可以使用 sed grep 等工具進行數據提取或者修改。
  • 與存儲引擎無關,因為備份文件是直接從 MySQL 里面提取出來的數據,所以在直觀上,備份數據數據不對引擎做區分,可以很方便地從 MyISAM 引擎改到 InnoDB 引擎。
  • 避免受到文件損壞的影響,如果直接復制原始文件,可能會受到某個文件損壞的影響而得到一個損壞的備份。使用邏輯備份,只要 MySQL 還能執行 SELECT 語句,就可以得到一份可以信賴的邏輯備份,在文件損壞的時候很有用。

邏輯備份缺點:

  • 因為必須使用 MySQL 服務進行數據操作,所以備份的時候會占用更多 CPU,且備份時間可能會更長。
  • 邏輯備份在某些場景下比數據庫文件更大,文本存儲的數據不總是比存儲引擎更高效。當然,使用壓縮的話會得到一個更小的備份,但是要占用 CPU 資源。(如果索引較多,邏輯備份會比物理備份小。)
  • 恢復時間更長,使用邏輯備份的數據恢復,需要占用更多資源去進行鎖分配、索引構建、沖突檢查、日志刷新。

邏輯備份常用方法:

  • mysqldumpMySQL自帶的備份工具,通用性強,非常常見。使用的使用通常要加上一些參數,后面繼續介紹。
  • select into outfile,以符號分割數據創建邏輯備份,對於要導入到 CSV 等表格會比較實用。
  • mydumper,允許使用多線程進行備份,備份文件會進行表結構和數據分離,在恢復某些表或數據的時候會非常有效。

1.2.2 物理備份

物理備份在數據量較大的時候非常常見。

物理備份的優勢:

  • 備份速度快,因為物理備份是基於復制進行備份,意味者復制有多快,備份就能有多快。
  • 恢復速度快,只需要把文件復制到數據庫目錄就可以完成恢復,不需要檢查鎖、構建索引。
  • 恢復簡單,對於 MySIAM 引擎的表,不需要停庫,只需要簡單地復制進數據目錄就可以。對於 InnoDB,如果是每個表一個表空間,也可以不停庫操作,使用卸載加載表空間的方式便可導入(不太安全)。

物理備份缺點:

  • 沒有官方物理熱備份工具的支持。沒有官方工具的支持,意味着出問題的概率較大,使用的時候就要謹慎了
  • InnoDB 的原始文件通常比邏輯備份要大。InnoDB 表空間往往包含很多未被使用的空間,InnoDB 表在刪除數據后不會釋放空間,所以即使數據量不大,文件有可能很大。除此以外,文件中除了數據還包含了索引、日志等信息。
  • 物理備份不總可以跨平台跨版本。MySQL 文件和操作系統、MySQL 版本息息相關,如果環境與原來不一致,很有可能會出現問題。

物理備份常用方法:

  • xtrabackup 是最常用的物理備份工具,由 percona 開源,能夠實現對 InnoDB 存儲引擎和 XtraDB 存儲引擎非阻塞地備份(對於 MyISAM 還是要加鎖),得到一份一致性備份。
  • 直接復制文件/文件系統快照,這種方式對於 MySIAM 引擎是非常高效的,只需要執行 FLUSH TABLE WITH READ LOCK 就可以復制得到一份備份文件。但是對於 InnoDB 引擎就比較困難,因為 InnoDB 引擎使用了大量的異步技術,即使執行了 FLUSH TABLE WITH READ LOCK,它還是會繼續合並日志、緩存數據。所以要用這種方法備份 InnoDB,需要確保 checkpoint 已經最新。

1.2 為什么要備份 binlog

如果有 DBA 告訴你,這個數據庫能夠恢復到兩個個月內任何狀態,這說明了,這個數據庫的 binlog 日志至少保留了兩個月。備份 binlog 的好處:

  • 可以實現基於任意時間點的恢復
  • 可以用於誤操作數據閃回
  • 可以用於審計

當你要進行數據恢復的時候,就會非常慶幸有做 binlog 備份。當然,使用 binlog 恢復數據的前提是 binlog 格式要設為 row,不要擔心空間問題,當前最不缺的資源就是硬盤空間。對於 binlog,我們推薦的配置是

# 記錄每一行數據的變化
binlog_format = row
# 備庫在重做數據的時候,記錄一條 binlog
log_slave_updates = 1

1.3 復制和備份

主從復制等於多了一個數據副本,但是復制並不等於備份,也不能代替備份。假設在主庫執行了 drop table 操作,會立刻同步到備庫,並執行相同的操作,沒有辦法在出現意外的時候使用備庫進行數據恢復。

延遲復制也不能代替備份,但是能加快恢復的速度,是一種非常有用的策略。

在實際使用中,為了不影響主庫的使用,我們往往會在備庫進行備份,同時記錄同步點,以方便進行新備庫搭建。在備庫備份需要注意的是,主從復制並不能保證主備間數據是一致的。實際上,基於復制的 MySQL 集群並不能保證集群內部一致性,當前也沒有非常好的辦法,常用的是使用 pt-table-checksum 進行一致性檢查。

2. 全量備份

全量備份介紹最常用的邏輯備份工具 mysqldump 和物理備份工具 xtrabackup。如果對 mysqldump 不太滿意 可以使用 mydumper 來替代 mysqldump

2.1 mysqldump

mysqldump 是用得最多的工具,但是要用好的話,需要增加一些額外的參數。mysqldump 有很多可用參數,這里不展開,建議直接訪問官網 mysqldump。使用 mysqldump 某些參數需要 select,reload,lock tables 權限。

2.1.1 常見例子

2.1.1.1 InnoDB 全庫備份

mysqldump --opt --single-transaction --master-data=2 --default-character-set=utf8 -h<host> -u<user> -p<password> -A > backup.sql
  • --opt 如果有這個參數表示同時激活了mysqldump命令的quick,add-drop-table,add-locks,extended-insert,lock-tables參數,它可以給出很快的轉儲操作並產生一個可以很快裝入MySQL服務器的轉儲文件。當備份大表時,這個參數可以防止占用過多內存
  • --single-transaction 設置事務的隔離級別為可重復讀,然后備份的時候開啟事務,這樣能保證在一個事務中所有相同的查詢讀取到同樣的數據。注意,這個參數只對支持事務的引擎有效,如果有 MyISAM 的數據表,並不能保證數據一致性
  • -A 導出全部數據庫
  • –-default-character-set=charset 指定導出數據時采用何種字符集
  • --master-data=2 表示在備份過程中記錄主庫的 binlogpos 點,並在dump文件中注釋掉這一行,在使用備份文件做新備庫時會用到

2.1.1.2 MyISAM 全庫備份

mysqldump --opt --lock-all-tables --master-data=2 --default-character-set=utf8 -h<host> -u<user> -p<password> -A > backup.sql
  • --lock-all-tables 鎖表備份。由於 MyISAM 不能提供一致性讀,如果要得到一份一致性備份,只能進行全表鎖定。

2.1.1.3 備份帶上壓縮

mysqldump -h<host> -u<user> -p<password> -A | gzip >> backup.sql.gz

2.1.1.4 備份多個庫

mysqldump -h<host> -u<user> -p<password> --databases <dbname1> <dbname2> > backup.sql

2.1.2 恢復

恢復方式比較簡單,直接執行 sql 語句就可以了

mysql -h<host> -u<user> -p<password> < backup.sql

2.1.3 mysqldump執行流程

打開 general_log 可以查看 mysqldump 的執行流程,這里以 --single-transaction --opt -A 參數為例

FLUSH /*!40101 LOCAL */ TABLES
FLUSH TABLES WITH READ LOCK
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
START TRANSACTION
SHOW VARIABLES LIKE 'gtid\_mode'
SHOW MASTER STATUS
UNLOCK TABLES
...
SHOW CREATE DATABASE IF NOT EXISTS `employees`
SAVEPOINT sp
...
SELECT /*!40001 SQL_NO_CACHE */ * FROM `departments`
....

2.2 xtrabackup

2.2.1 安裝方式

更多安裝方式參考官網 xtrabackup

這里我們使用 rpm 安裝的方式

yum install http://www.percona.com/downloads/percona-release/redhat/0.1-6/percona-release-0.1-6.noarch.rpm
yum update percona-release
# qpress 用作壓縮解壓
yum install percona-xtrabackup-24 qpress

2.2.2 使用方法

2.2.2.1 增加備份賬號並授權

CREATE USER 'backup'@'localhost' IDENTIFIED BY 'backup';
GRANT PROCESS,RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup'@'localhost';
FLUSH PRIVILEGES;

2.2.2.2 全備

innobackupex --defaults-file=/etc/my.cnf --user=<user> --password=<pwd> <要備份到哪個目錄> --no-timestamp --compress --compress-threads=4 --parallel=4
  • --no-timestamp 不使用當前時間建立文件夾。默認情況下會在備份目錄以當前時間創建文件夾
  • --compress 壓縮
  • --compress-threads=N 壓縮線程
  • --parallel=N 備份線程

2.2.2.3 恢復

# 步驟一:解壓
innobackupex --decompress <備份文件所在目錄> --parallel=4

# 步驟二:應用日志
innobackupex --apply-log <備份文件所在目錄> --parallel=4

# 步驟三:復制備份文件到數據目錄
innobackupex --datadir=<MySQL數據目錄> --copy-back <備份文件所在目錄> --parallel=4

3. 增量備份

當數據了變得龐大時,一個常見策略就是做定期的增量備份。例如:周一做了一次全量備份,然后周二到日做增量備份。

增量備份只包含變化的數據集,一般情況不會比原始數據量大,所以可以減少服務器的開銷、備份時間、備份空間。

當然,使用增量備份也會有風險,增量備份每一次迭代都是基於上一次的備份實現,意味着只要其中一份備份出現問題,那么就有可能導致所有備份不可用。

下面介紹一些增量備份方法:

3.1 使用 xtrabackup 做增量備份

xtrabackup 允許進行增量備份,命令如下:

innobackupex --defaults-file=/etc/my.cnf --user=<user> --password=<pwd> --no-timestamp --compress --incremental --incremental-basedir=<全量備份的目錄> <要增量備份到什么目錄>

恢復:

# 步驟一:對全備解壓
innobackupex --decompress <全量備份文件所在目錄>

# 步驟二:對全備應用日志
innobackupex --apply-log --redo-only <全量備份文件所在目錄>

# 步驟三:對增量備份進行解壓
innobackupex --decompress <增量文件所在目錄>

# 步驟四:合並增量數據
innobackupex --apply-log --redo-only --incremental <全量備份文件所在目錄> --incremental-dir=<增量文件所在目錄>

# 步驟五:對合並后的數據應用日志
innobackupex --apply-log <全量備份文件所在目錄>

# 步驟六:復制備份文件到數據目錄
innobackupex --datadir=<MySQL數據目錄> --copy-back <全量備份文件所在目錄>

3.2 使用 binlog 做增量備份

使用 binlog 做增量備份比較簡單,備份的時候執行 FLUSH LOGS 輪轉日志,然后把舊的 binlog 復制到備份目錄就可以了。

恢復的時候使用 mysqlbinlog --start-position=<備份集的pos點> binlog日志 | mysql -u<user> -p 就可以了

4. 延遲同步

延遲同步是常見的使用主從復制使用模式,在遇到誤操作的時候,無論是用於恢復數據,還是使用跳過的方式跳過錯誤都是非常有用。

例如在主庫做了 drop 的誤操作,在主庫找到命令所在 binlog 日志和 pos 位置,Delay庫停止同步,然后使用 start slave until master_log_file='<對應file>',master_log_pos=<誤操作命令前一個SQL的pos>; 等待同步到這個位置,執行跳過一條 SQL 的命令再開啟同步。

常見的延遲同步復制模式有:

一主帶三從

有時候為了減少主庫壓力,會把延遲庫放在備節點之后

延遲同步開啟方式如下:

stop slave;
CHANGE MASTER TO MASTER_DELAY = N秒;
start slave;

5. 數據校驗

除了備份,非常重要的一件事情就是驗證備份數據的可用性。想象一下,當你需要進行數據恢復的時候,忽然發現過去的備份數據都是無效的,那得有多難受。很多朋友在寫好備份腳本加到定時任務后,只要檢查到定時任務有執行,備份目錄有文件就不再關注了,往往到了需要使用備份文件的時候才發現備份數據有問題。

目前對於備份文件的數據校驗沒有非常方便的辦法,用的比較多的還是定時把備份文件拉出來做備份恢復演練,例如一個月做一次備份恢復演練就可以有效提高備份文件可用性,心里也踏實。

數據校驗部分,如果是邏輯備份,往往會抽查某個表的數據,檢查是否符合預期。如果是物理備份,首先要使用 mysqlcheck 等命令檢查是否有表損壞,沒有損壞再抽查表數據。

6. 總結

  1. 邏輯備份和物理備份可以一起使用,不同的備份周期使用不同的工具,全備周期不應該太長,至少一周一次全備
  2. 如果數據量較大,可以使用增量備份的方式減少數據量,要注意的是,增量備份風險更大
  3. binlog功能要開啟,設為 row 模式,設置 log_slave_updates = 1,且最好定時備份 binlog
  4. 有條件的話可以增加一個 Delay 庫,在做緊急恢復的時候有奇效
  5. 數據校驗要定時去做,否則當需要備份恢復的時候而備份文件又失效,后悔都來不及


免責聲明!

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



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