天天看點

MySQL深入09-備份-恢複

備份的目的

  • 災難恢複;
  • 資料審計;
  • 測試;

備份類型

根據備份時,資料庫伺服器是否線上:

  • 冷備:cold backup
  • 溫備:warm backup,全局施加共享鎖,允許讀,禁止寫
  • 熱備:hot backup

根據備份的資料集:

  • 完全備份:full backup
  • 部分備份:partial backup

根據備份時的接口:是直接備份資料檔案還是通過mysql伺服器導出資料

  • 實體備份:直接複制(或打包歸檔)資料檔案的備份方式,physical backup
    • 優點: 無需額外工具,直接copy即可;恢複直接複制備份檔案即可
    • 缺點:與存儲引擎有關,跨平台能力較弱
  • 邏輯備份:把資料從庫中提取出來,并儲存為文本檔案,logical backup,工具是mysqldump
    • 優點: 能使用編輯器處理;恢複簡單;能基于網絡恢複;有助于避免資料損壞
    • 缺點: 備份檔案較大,備份較慢;無法保證浮點數的精度;使用邏輯備份資料恢複後,還需手動重建索引,十分消耗CPU資源

根據備份時的資料變化方式:

  • 增量備份:incremental backup,節約空間;對上次完全備份或增量備份後變化的資料進行備份
  • 差異備份:differential backup,容易恢複;對上次完全備份後的差異資料進行備份

備份政策

  • 選擇合适的備份方式;
  • 選擇備份時間;
  • 考慮到恢複成本(主要是恢複時長);
  • 考慮備份成本(包括 鎖時間,備份時長,備份負載等);
  • 備份的難度取決于所能容忍的資料丢失量;

備份對象

  • 資料檔案;
  • 代碼:存儲過程,存儲函數,觸發器等;
  • OS相關的配置檔案,如crontab配置計劃及相關腳本;
  • 跟複制相關的配置資訊
  • 二進制日志檔案;

備份工具

mysqldump:邏輯備份工具

  • InnoDB熱備、MyISAM溫備、Aria溫備;
  • 單線程備份工具;

mysqldumper:多線程的mysqldump

  • 很難實作差異或增量備份

lvm-snapshot:

  • 實作接近于熱備的工具,因為要先請求全局鎖,而後建立快照,并在建立快照完成後釋放全局鎖;
  • 使用cp,tar等工具進行實體備份;
  • 備份和恢複速度都較快;
  • 很難實作增量備份,并且請求全局鎖需要等待一段時間,在繁忙的伺服器上尤其如此;

指令行下的部分備份資料工具

  • 備份:select clause into outfile ‘/path/to/somefile’
  • 恢複:load data infile ‘/path/from/somefile’
  • 不會備份關系定義,僅備份表中的資料
  • 邏輯備份工具,快于mysqldump

innobackup:商業備份工具,Innobase

Xtrabackup:由Percona提供的開源備份工具

  • InnoDB熱備:增量備份;
  • MyISAM溫備:不支援增量備份;
  • 實體備份,速度快;

mysqlhotcopy:是一個Perl腳本

  • 隻能用于備份MyISAM庫,且資料恢複需要重新開機mysql,故基本可認為是冷備;

mysqldump

适用場景:建議備份資料在5G以下,資料超過10G不建議使用此工具

用法:mysqldump [options] [db_name [tbl_name…]]

  • 備份單個庫:mysqldump [options] db_name
    • 備份時,不建立庫,隻備份庫中的表;
    • 故恢複時,若目标庫不存在,則需要事先手動建立資料庫;
  • 備份多個庫:--databases db1,db2
    • --databases db1 # 備份單庫時建議使用,這樣備份時也能備份庫,在恢複時無需建立資料庫;

其它備份選項:

--all-databases # 備份所有庫;
--lock-all-tables # 請求鎖定所有表後再備份,對MyISAM、InnoDB、Aria做溫備;
--single-transaction # 能夠對InnoDB存儲引擎實作熱備;
--events # 備份事件排程器代碼;
--routines # 備份存儲過程和存儲函數;
--triggers # 備份觸發器;
--flush-logs # 備份前,請求到鎖後先滾動日志再備份
--master-data=[0|1|2] # 記錄複制時二進制日志的同步位置
0:不記錄;
1:記錄CHANGE MASTER語;
2:記錄為注釋的CHANGE MASTER語句;      

備份步驟

  1. 請求鎖:--lock-all-tables或--single-transaction進行innodb熱備;
  2. 滾動日志:--flush-logs;
  3. 標明要備份的庫:--databases;
  4. 記錄二進制日志檔案及位置:--master-data=2;
  5. 3種備份方法:
    # 手動鎖表,手動滾動日志:
    mysql> flush tables with read lock;
    mysql> flush logs;
    mysqldump --databases hdb > hdb1.sql
    mysql> unlock tables;
    # 對MyISAM溫備:
    mysqldump --databases hdb --lock-all-tables --flush-logs --master-data=2 > hdb.sql
    # 對InnoDB熱備:
    mysqldump --databases hdb --single-transaction --flush-logs --master-data=2 > hdb.sql      

資料恢複步驟

  1. 建議先關閉二進制日志(log_bin=OFF),并關閉其它使用者連接配接;
  2. 導入資料即可完成資料恢複:mysql < hdb.sql

基于mysqldump的備份政策

  • 備份:mysqldump+二進制日志檔案
    • 周日做一次完全備份:備份的同時滾動日志
    • 周一至周六:備份二進制日志
  • 恢複:
    • 完全備份資料+每天的二進制日志檔案

注:對于MySQL配置檔案,以及與MySQL相關的OS配置檔案在每次修改後都應該直接進行備份

lvm-snapshot

使用場景

  • 基于LVM快照的備份方式,故事務日志和資料檔案必須在同一個卷上;
  • 建立快照卷之前,要請求MySQL的全局鎖;在快照建立完成後釋放鎖;
  • 請求全局鎖完成之後,做一次日志滾動;并做二進制日志檔案及位置标記;
# 請求全局鎖,并滾動日志
mysql> flush tables with read lock;
mysql> flush logs;
# 做二進制日志檔案及位置标記(手動進行)
mysql -e ‘show master status’ > /backups/bin.pos
# 建立快照卷
lvcreate -s -L 100M -n /dev/myvg/mydata-snap -p r /dev/myvg/mydata
# 釋放全局鎖
mysql> unlock tables;
# 挂載快照卷并備份
mount /dev/myvg/mydata-snap /mnt -o ro
cp -a /mnt/data/ /backups/data/2014-04-11
# 備份完成之後,删除快照卷      
# 還原資料,修改權限及屬主屬組等,并啟動mysql
cp -a /backups/data/2014-04-11/* /mydata/data/
# 提取備份之後的所有事件至某sql腳本中,并做即時點還原
cat /backups/bin.pos
mysqlbinlog --start-position=# --stop-position=# mysql-bin.# > bak.sql
mysql < bak.sql      

mylvmbackup:是一個perl腳本,能夠實作基于LVM的快速備份MySQL資料檔案,對于上面介紹的備份操作可實作自動化一鍵完成

  • 官方位址是:http://www.lenzg.net/mylvmbackup/
  • 需要安裝的Perl5子產品有:DBI、DBD:mysql、Config::IniFiles、TimeDate、File::Copy::Recursive、Sys::Syslog、MIME::Lite
    • 可通過cpan自動安裝,如 cpan Config::IniFiles
  • 安裝後,稍微配置一下其配置檔案/etc/mylvmbackup.conf即可,然後執行mylvmbackup指令即可完成基于LVM的資料備份過程了;

Xtrabackup

适用場景:由percona提供的mysql資料庫備份工具,能夠實作對innodb和xtradb資料庫進行線上熱備;

特點:

  • 備份過程快速、可靠;
  • 備份過程不會打斷正在執行的事務;
  • 能夠基于壓縮等功能節約磁盤空間和流量;
  • 自動實作備份檢驗;
  • 還原速度快;

安裝:

yum --nogpgcheck localinstall percona-xtrabackup-2.1.8-733.rhel6.x86_64.rpm # 備份工具包
yum --nogpgcheck localinstall percona-toolkit-2.2.4-1.noarch.rpm # 包含衆多pt-*工具,可完整資料一緻性檢測,表資料同步等功能
percona-xtrabackup包中包含的2個工具:
xtrabackup # 是用于熱備份innodb, xtradb表中資料的工具,不能備份其他類型的表,也不能備份資料表結構;
innobackupex # 是将xtrabackup進行封裝的perl腳本,提供了備份myisam表的能力      

備份步驟:

完全備份:

innobackupex --user=root --password=magedu /data/backups/ # 隻需指定備份檔案所在目錄即可
# 如果要使用一個最小權限的使用者進行備份,則可基于如下指令建立此類使用者:
mysql> create user ’bkuser’@’localhost’ identified by ’bkpass’;
mysql> revoke all privileges,grant option from 'bkuser';
mysql> grant reload,lock tables,replication client on *.* to 'bkuser'@'localhost';
mysql> flush privileges;
# 使用innobakupex備份時,其會調用xtrabackup備份所有的InnoDB表,複制所有關于表結構定義的相關檔案(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相關檔案,同時還會備份觸發器和資料庫配置資訊相關的檔案。這些檔案會被儲存至一個以時間指令的目錄(如2014-04-23_17-34-45)中;
# 在備份的同時,innobackupex還會在備份目錄中建立如下檔案:
xtrabackup_checkpoints # 備份類型(如完全或增量)、備份狀态(如是否已經為prepared狀态)和LSN(日志序列号)範圍資訊;
xtrabackup_binlog_info  # mysql伺服器目前正在使用的二進制日志檔案及至備份這一刻為止二進制日志事件的位置;
xtrabackup_binary # 備份中用到的xtrabackup的可執行檔案;
backup-my.cnf # 備份指令用到的配置選項資訊;      

增量備份:

  • 每個InnoDB的頁面都會包含一個LSN資訊,每當相關的資料發生改變,相關的頁面的LSN就會自動增長。這正是InnoDB表可以進行增量備份的基礎,即innobackupex通過備份上次完全備份之後發生改變的頁面來實作;
    innobackupex --incremental /data/backups/ --incremental-basedir=/data/backups/2014-04-23_17-44-51/ # 還需指定需做增量備份的完全備份的目錄路徑      
  • innobackupex指令會在/data/backups/目錄中建立一個新的以時間命名的目錄以存放所有的增量備份資料。另外,在執行過增量備份之後再一次進行增量備份時,其--incremental-basedir應該指向上一次的增量備份所在的目錄;
  • 注:增量備份僅能應用于InnoDB或XtraDB表,對于MyISAM表而言,執行增量備份時其實進行的是完全備份;

資料恢複步驟:分準備和恢複兩個階段進行

準備階段:

 一般情況下,在備份完成後,資料尚且不能用于恢複操作,因為備份的資料中可能會包含尚未送出的事務或已經送出但尚未同步至資料檔案中的事務。是以,此時資料檔案仍處理不一緻狀态。“準備”的主要作用正是通過復原未送出的事務及同步已經送出的事務至資料檔案也使得資料檔案處于一緻性狀态;

完全備份準備:

innobackupex --apply-log /data/backups/2014-04-23_17-34-45 # 使用apply-log選項,并指定需“準備”的備份目錄即可      

增量備份準備:

innobackupex --apply-log --redo-only /data/backups/2014-04-23_17-44-51 # 首先對完全備份目錄進行“準備”
innobackupex --apply-log --redo-only /data/backups/2014-04-23_19-48-27 # 然後對第一次增量備份目錄進行“準備”
innobackupex --apply-log --redo-only /data/backups/2014-04-23_19-56-26 # 然後對第二次增量備份目錄進行“準備”      

注:在實作“準備”的過程中,innobackupex通常還可以使用--use-memory選項來指定其可以使用的記憶體的大小,預設通常為100M。如果有足夠的記憶體可用,可以多劃分一些記憶體給prepare的過程,以提高其完成速度;

增量備份的“準備”階段與完全備份的“準備”階段略有不同:

  • 需要在每個備份(包括完全和各個增量備份)上,将已經送出的事務進行“重放”;“重放”之後,所有的備份資料将合并到完全備份上;
  • 基于所有的備份将未送出的事務進行“復原”;

恢複階段:

innobackupex --copy-back /data/backups/2014-04-23_17-34-45 # 完全備份恢複資料;若有增量備份,則需完成準備階段後,再利用完全備份目錄進行資料恢複
chown -R mysql:mysql /data/mysqldata/ # 當資料恢複至DATADIR目錄以後,還需要修改資料檔案的屬主和屬組,如mysql
service mysqld start # 啟動mysql即可,資料恢複完成      

總結:以上介紹的MySQL資料備份方式是最常見的3種方式,最強大的當然是Xtrabackup(畢竟人家可以熱備份嘛),但需提前安裝備份工具;而在測試環境,使用mysqldump也不失為一種快捷的方式;若MySQL的資料檔案是位于LVM磁盤上,且資料檔案較大,則也可考慮利用lvm-snapshot方式;

資料備份準則:

  • 将資料和備份放在不同的磁盤裝置上,異地或異機備份存儲較為理想;
  • 備份的資料應該周期性地進行還原測試;
  • 每次災難恢複後都應該立即做一次完全備份;
  • 針對不同規模或級别的資料量,要制定好備份政策;
  • 二進制日志應該跟資料檔案在不同磁盤上,并周期性地備份好二進制日志檔案;

從備份中恢複資料應該遵循的步驟:

  • 停止MySQL伺服器;
  • 記錄伺服器的配置和檔案權限;
  • 将資料從備份移到MySQL資料目錄,其執行方式依賴于工具,如innobackupex --copy-back;
  • 改變配置和檔案權限;
  • 以限制通路模式重新開機伺服器:
    • skip-networking # 此選項可使MySQL跳過網絡功能
    • socket=/tmp/mysql-recovery.sock
    • 方法:編輯my.cnf配置檔案,添加如下項:
  • 載入邏輯備份(如果有);檢查和重放二進制日志;
  • 檢查已經還原的資料是否可用;
  • 重新以完全通路模式重新開機伺服器;
  • 注釋前面在my.cnf中添加的選項即可,并重新開機MySQL;

其它可參考備份方式:

Xtrabackup的“流”及“備份壓縮”功能

Xtrabackup對備份的資料檔案支援“流”功能,即可以将備份的資料通過STDOUT傳輸給tar程式進行歸檔,而不是預設的直接儲存至某備份目錄中。要使用此功能,僅需要使用--stream選項即可:

innobackupex --stream=tar /data/backups | gzip > /data/backups/`date +%F_%H-%M-%S`.tar.gz # 歸檔并壓縮後儲存在本地
innobackupex --stream=tar /data/backups | ssh [email protected] "cat - > /backups/`date +%F_%H-%M-%S`.tar" # 歸檔儲存在遠端主機,
innobackupex --parallel=2  /data/backups # 在執行本地備份時,可以使用--parallel指定在複制時啟動的線程數目,實作多個檔案的并行複制;      

注:将備份資料儲存至遠端主機時,需保證可通過ssh直接登入遠端主機而無需密碼,即需進行ssh授權

Xtrabackup導入或導出單張表

預設情況下,InnoDB表不能通過直接複制表檔案的方式在mysql伺服器之間進行移植;

而使用Xtrabackup工具可以實作此種功能,不過,此時需要“導出”表的mysql伺服器啟用了innodb_file_per_table選項,并且“導入”表的伺服器同時啟用了innodb_file_per_table和innodb_expand_import選項;

導出表

導出表是在備份的準備階段(prepare)進行的,是以,一旦完全備份完成,就可以在prepare過程中通過--export選項将某表導出了:

innobackupex --apply-log --export /path/to/backup # 此指令會為每個innodb表的表空間建立一個以.exp結尾的檔案,這些以.exp結尾的檔案則可以用于導入至其它伺服器;      

導入表

要在mysql伺服器上導入來自于其它伺服器的某innodb表,需要先在目前伺服器上建立一個跟原表表結構一緻的表,而後才能實作将表導入:

mysql> CREATE TABLE mytable (...)  ENGINE=InnoDB;
# 然後将此表的表空間删除:
mysql> ALTER TABLE mydatabase.mytable  DISCARD TABLESPACE;
# 接下來,将來自于“導出”表的伺服器的mytable表的mytable.ibd和mytable.exp檔案複制到目前伺服器的資料目錄,然後使用如下指令将其“導入”:
mysql> ALTER TABLE mydatabase.mytable  IMPORT TABLESPACE;      

上一篇:MySQL深入08-日志及其參數設定