天天看點

MySQL備份恢複之XtraBackup

一、 簡介

        我們知道,針對innodb存儲引擎,mysql本身沒有提供合适的熱備工具,ibbackup雖是一款高效的首選熱備方式,但它是是收費的。好在percona公司給大家提供了一個開源、免費的xtrabackup熱備工具,它可實作ibbackup的所有功能,并且還擴充支援真正的增量備份功能,是商業備份工具innodb hotbackup的一個很好的替代品。

xtrabackup包括兩個主要工具:xtrabackup和innobackupex:

xtrabackup隻能備份innodb和xtradb兩種引擎表,而不能備份myisam資料表。

innobackupex則是參考innodbhotbackup的innoback腳本修改而來的一個perl腳本,它封裝了xtrabackup,主要是為了能友善的同時備份innodb和myisam引擎表。但在處理myisam時需要加一個讀鎖,這會阻塞線上服務的寫操作,是以資料庫中myisam表越少越好。另外,該工具還加入了一些其它使用選項,比如slave-info,可以在備份中記錄一些slave需要的資訊,根據這些資訊,可以很友善的利用備份重做slave。

        通過xtrabackup,不但可線上(熱)備份整個庫的innodb、xtradb表,還可在上一次整庫備份的基礎上做增量備份(innodb only),其工作原理如下:

        首先完成一個完全備份,并記錄下此時檢查點的lsn(log sequence number);在進行增量備份時,比較表空間中每個頁的lsn是否大于上次備份時的lsn,如果是,則備份該頁,同時記錄目前檢查點的lsn。

注意:在增量備份時,作為備份基礎的全備檔案不能壓縮,否則備份失效;另外,增量備份期間,表結構變更的話,變更部分的備份也會失效。

二、安裝

         pecona官方網站提供了xtrabackup源碼包、二進制包以及rpm包三種安裝包,下載下傳位址為:http://www.percona.com/downloads/xtrabackup/ 本文選擇最簡單友善的rpm包安裝,如下:

[root@db ~]# rpm -ivh percona-xtrabackup-2.0.5-499.rhel5.x86_64.rpm

warning: percona-xtrabackup-2.0.5-499.rhel5.x86_64.rpm:header v4 dsa signature: nokey, key id cd2efd2a

preparing...               ########################################### [100%]

  1:percona-xtrabackup    ########################################### [100%]

   安裝完成後,會在/usr/bin/目錄下生成如下指令工具:

[root@db ~]# cd /usr/bin/

[root@db bin]# ls xtr* inno*

innobackupex    innochecksum xtrabackup_51  xtrapchar  xtrapinfo xtrapproto  xtrapstats

innobackupex-1.5.1  xtrabackup   xtrabackup_55  xtrapin    xtrapout  xtrapreset

其中:

innobackupex                                 是備份時直接使用的工具,它是一個perl腳本,内部封裝xtrabackup;

innobackupex-1.5.1                       是innobackupex檔案的一個軟連結;

xtrabackup                                       是備份innodb引擎的腳本;

xtrabackup_51                                xtrabackup運作時需要調用的工具,适用于mysql 5.1版本;

xtrabackup_55                                xtrabackup運作時需要調用的工具,适用于mysql 5.5版本;

三、xtrabackup的使用

        首先來學習使用xtrabackup這個指令工具,前面提到:它隻能備份innodb和xtradb兩種引擎表,不能備份myisam資料表。

通過--help參數檢視該指令的用法,如下:

usage: [xtrabackup  [--default-file=#]   --backup |  xtrabackup [--defaults-file=#] --prepare] [options]

參數解讀如下:

<col>

--defaults-file=#

辨別預設的配置檔案,可顯式手工指定,也可不設定;若不設定,則xtrabackup預設将從以下目錄查找配置檔案:

/etc/my.cnf    

/etc/mysql/my.cnf       

/usr/local/etc/my.cnf 

~/.my.cnf 

然後從中讀取[mysqld]和[xtrabackup]配置段。[mysqld]中隻需指定datadir、innodb_data_home_dir、innodb_data_file_path、innodb_log_group_home_dir、innodb_log_files_in_group、innodb_log_file_size這6個參數即可讓xtrabackup正常工作。

--defaults-extra-file=#

如果使用了該參數,則會在讀取了全局配置檔案後,再讀取這裡指定的配置檔案

--target-dir=name

備份檔案的存放路徑

--backup 

 執行備份操作,将備份檔案存放到target-dir指定的目錄下

--prepare

對備份檔案執行恢複前的準備(生成innodb logfile)

--print-param

列印備份或恢複時需要的參數

--use-memory=# 

該參數在prepare的時候使用,控制prepare時innodb執行個體使用的記憶體量

--suspend-at-end

 在target-dir目錄下産生一個xtrabackup_suspended檔案,将xtrabackup程序挂起,不停地将資料檔案的變化同步到備份檔案,直到使用者手工删除xtrabackup_suspended檔案

--throttle=#

每秒鐘io次數,限制backup時使用的i/o操作量,使備份對資料庫正常業務的影響最小化

--log-stream 

該參數在backup時使用,将xtrabackup_logfile的内容輸出到标準輸出,使用該參數時會自動使用suspend-at-end參數,innobackupex腳本的stream模式會使用該參數。

--incremental-lsn=name

增量備份時隻拷貝lsn比該參數指定值新的ibd pages,前次備份到了哪個lsn可以看前次備份集的xtrabackup_checkpoints檔案

--incremental-basedir=name

該參數在backup的時候使用,備份比該參數指定位置的備份集新的idb pages

--incremental-dir=name

該參數在prepare的時候使用,指定prepare時産生的delta檔案和日志檔案的存放路徑

--tables=name

在備份file-per-table類型的檔案時使用,使用正規表達式指定需要備份的innodb表

-h, --datadir=name

mysql資料庫的資料檔案目錄

示例1:完全備份與恢複(innodb)

(1)備份

腳本内容:

[root@db xtrabak]# more xtra_backup.sh 

# 2014-04-29

mkdir -p /data/xtrabak/bak_`date +%f`/

echo "backup begin" `date`

xtrabackup --defaults-file=/etc/my.cnf --backup --target-dir=/data/xtrabak/bak_`date +%f`/

cp -r /var/lib/mysql/test /data/xtrabak/bak_`date +%f`/

注意:xtrabackup隻備份資料檔案,并不備份資料表結構檔案(.frm),是以還需手動拷貝一下,以便xtrabackup恢複時使用

執行備份腳本:

[root@db xtrabak]# sh xtra_backup.sh 

backup begin tue apr 29 15:22:09 cst 2014

xtrabackup version 2.0.5 for percona server 5.1.59 unknown-linux-gnu (x86_64) (revision id: 499)

xtrabackup: uses posix_fadvise().

xtrabackup: cd to /var/lib/mysql/

xtrabackup: target instance is assumed as followings.

xtrabackup:   innodb_data_home_dir = /var/lib/mysql

xtrabackup:   innodb_data_file_path = ibdata1:10m:autoextend

xtrabackup:   innodb_log_group_home_dir = /var/lib/mysql

xtrabackup:   innodb_log_files_in_group = 2

xtrabackup:   innodb_log_file_size = 5242880

&gt;&gt; log scanned up to (1830807)

[01] copying /var/lib/mysql/ibdata1 to /data/xtrabak/bak_2014-04-29/ibdata1

[01]        ...done

xtrabackup: the latest check point (for incremental): ‘1830807‘

xtrabackup: stopping log copying thread.

.&gt;&gt; log scanned up to (1830807)

xtrabackup: transaction log of lsn (1830807) to (1830807) was copied.

從輸出可以看出,備份過程首先記錄lsn,然後拷貝資料檔案(注意,并沒有備份表結構檔案.frm),最後拷貝并記錄lsn。備份完成後,在指定目标目錄除了拷貝過來的資料檔案ibdata1及表結構檔案夾test外,還生成了另外兩個檔案,分别記錄日志及檢查點,如下:

[root@db xtrabak]# cd bak_2014-04-29/

[root@db bak_2014-04-29]# ls

ibdata1  test  xtrabackup_checkpoints  xtrabackup_logfile

恢複

删除庫test,然後通過備份檔案執行恢複,如下:

[root@db xtrabak]# more xtra_prepare.sh 

xtrabackup --defaults-file=/etc/my.cnf --prepare --target-dir=/data/xtrabak/bak_`date +%f`/

cp -r /data/xtrabak/bak_`date +%f`/test/ /var/lib/mysql/

rm /var/lib/mysql/ib*

cp /data/xtrabak/bak_`date +%f`/ib* /var/lib/mysql/

chown -r mysql:mysql /var/lib/mysql

service mysql restart

說明:腳本中步驟依次為:

實施對備份檔案進行恢複前的準備;

從備份檔案拷貝資料表結構到預設的資料目錄;

删除預設資料目錄中對應的資料檔案并複制備份的資料檔案到預設資料目錄;

修改預設資料目錄權限并重新開機mysql服務

執行恢複腳本:

[root@db xtrabak]# sh xtra_prepare.sh 

xtrabackup: cd to /data/xtrabak/bak_2014-04-29/

xtrabackup: this target seems to be not prepared yet.

xtrabackup: xtrabackup_logfile detected: size=2097152, start_lsn=(1830807)

xtrabackup: temporary instance for recovery is set as followings.

xtrabackup:   innodb_data_home_dir = ./

xtrabackup:   innodb_log_group_home_dir = ./

xtrabackup:   innodb_log_files_in_group = 1

xtrabackup:   innodb_log_file_size = 2097152

xtrabackup: starting innodb instance for recovery.

xtrabackup: using 104857600 bytes for buffer pool (set by --use-memory parameter)

innodb: the innodb memory heap is disabled

innodb: mutexes and rw_locks use gcc atomic builtins

innodb: compressed tables use zlib 1.2.3

140429 15:28:34  innodb: initializing buffer pool, size = 100.0m

140429 15:28:34  innodb: completed initialization of buffer pool

140429 15:28:34  innodb: highest supported file format is barracuda.

innodb: the log sequence number in ibdata files does not match

innodb: the log sequence number in the ib_logfiles!

140429 15:28:34  innodb: database was not shut down normally!

innodb: starting crash recovery.

innodb: reading tablespace information from the .ibd files...

innodb: last mysql binlog file position 0 85912, file name ./mysql-bin.000026

140429 15:28:34 percona xtradb (http://www.percona.com) 1.0.17-12.5 started; log sequence number 1830807

[notice (again)]

  if you use binary log and don‘t use any hack of group commit,

  the binary log position seems to be:

xtrabackup: starting shutdown with innodb_fast_shutdown = 1

140429 15:28:34  innodb: starting shutdown...

140429 15:28:34  innodb: shutdown completed; log sequence number 1832037

shutting down mysql....                                    [  ok  ]

starting mysql.                                            [  ok  ]

執行完成後,檢查發現test庫已成功恢複。

示例2:增量備份與恢複

增量備份是以完全備份或上一次增量備份為基礎的備份,适合資料庫很大的情況,支援線上熱備,備份期間不鎖定表,不影響使用者使用,備份恢複效率都比較高。

下面我們來模拟一次增量備份:

(1)  完全備份

現在test庫有三張表,執行一次完全備份

--腳本内容:

[root@db xtrabak]# more xtra_full_bak.sh 

mkdir -p /data/xtrabak/full_bak_`date +%f`/

xtrabackup --defaults-file=/etc/my.cnf --backup --target-dir=/data/xtrabak/full_bak_`date +%f`/

cp -r /var/lib/mysql/test/ /data/xtrabak/full_bak_`date +%f`/

--執行腳本

[root@db xtrabak]# sh xtra_full_bak.sh 

xtrabackup: cd to /var/lib/mysql

xtrabackup:   innodb_log_files_in_group = 3

xtrabackup:   innodb_log_file_size = 67108864

&gt;&gt; log scanned up to (1653514)

[01] copying /var/lib/mysql/ibdata1 to /data/xtrabak/full_bak_2014-04-29/ibdata1

xtrabackup: the latest check point (for incremental): ‘1653514‘

.&gt;&gt; log scanned up to (1653514)

xtrabackup: transaction log of lsn (1653514) to (1653514) was copied.

執行完成後,檢視備份檔案

[root@db xtrabak]# cd full_bak_2014-04-29/

[root@db full_bak_2014-04-29]# ls

(2)  增量備份

向test庫中添加一張新表,然後執行增量備份

[root@db xtrabak]# more xtra_delta_bak.sh 

mkdir -p /data/xtrabak/delta_bak_`date +%f`/

xtrabackup --defaults-file=/etc/my.cnf --backup --target-dir=/data/xtrabak/delta_bak_`date +%f`/ --incremental-basedir=/data/xtrabak/full_bak_`date +%f`/

說明:這裡需要再次拷貝test庫的表結構檔案,因為期間可能會增加或删除表

[root@db xtrabak]# sh xtra_delta_bak.sh 

incremental backup from 1653514 is enabled.

&gt;&gt; log scanned up to (1660436)

[01] copying /var/lib/mysql/ibdata1 to /data/xtrabak/delta_bak_2014-04-29/ibdata1.delta

xtrabackup: the latest check point (for incremental): ‘1660436‘

.&gt;&gt; log scanned up to (1660436)

xtrabackup: transaction log of lsn (1660436) to (1660436) was copied.

[root@db xtrabak]# cd delta_bak_2014-04-29/

[root@db delta_bak_2014-04-29]# ls

ibdata1.delta  ibdata1.meta  xtrabackup_checkpoints  xtrabackup_logfile

注意:在增量備份目錄下,資料檔案是以.delta結尾的,增量備份隻備份上一次完全備份後被修改過的page;當然,若再次執行增量備份,可以上一次完全備份為基礎,也可以第一次增量備份為基礎,每次增量備份的目錄都是需要修改的。

(3)  恢複

删除test庫,模拟故障,然後通過完全備份及增量備份檔案執行恢複。

[root@db xtrabak]# more xtra_delta_prepare.sh 

xtrabackup --defaults-file=/etc/my.cnf --prepare --target-dir=/data/xtrabak/full_bak_`date +%f`/

xtrabackup --defaults-file=/etc/my.cnf --prepare --target-dir=/data/xtrabak/full_bak_`date +%f`/ --incremental-dir=/data/xtrabak/delta_bak_`date +%f`/

cp -r /data/xtrabak/full_bak_`date +%f`/test/ /var/lib/mysql/

cp /data/xtrabak/full_bak_`date +%f`/ib* /var/lib/mysql/

[root@db xtrabak]# sh xtra_delta_prepare.sh 

xtrabackup: cd to /data/xtrabak/full_bak_2014-04-29/

xtrabackup: xtrabackup_logfile detected: size=2097152, start_lsn=(1653514)

140429 18:28:21  innodb: initializing buffer pool, size = 100.0m

140429 18:28:21  innodb: completed initialization of buffer pool

140429 18:28:21  innodb: highest supported file format is barracuda.

140429 18:28:21  innodb: database was not shut down normally!

innodb: last mysql binlog file position 0 2596, file name ./mysql-bin.000043

140429 18:28:22 percona xtradb (http://www.percona.com) 1.0.17-12.5 started; log sequence number 1653514

140429 18:28:22  innodb: starting shutdown...

140429 18:28:22  innodb: shutdown completed; log sequence number 1653514

xtrabackup: this target seems to be already prepared.

xtrabackup: xtrabackup_logfile detected: size=2097152, start_lsn=(1660436)

xtrabackup:   innodb_log_group_home_dir = /data/xtrabak/delta_bak_2014-04-29/

xtrabackup: page size for /data/xtrabak/delta_bak_2014-04-29//ibdata1.delta is 16384 bytes

applying /data/xtrabak/delta_bak_2014-04-29//ibdata1.delta to ././ibdata1...

140429 18:28:22  innodb: initializing buffer pool, size = 100.0m

140429 18:28:22  innodb: completed initialization of buffer pool

140429 18:28:22  innodb: highest supported file format is barracuda.

140429 18:28:22  innodb: database was not shut down normally!

innodb: last mysql binlog file position 0 2703, file name ./mysql-bin.000045

140429 18:28:22 percona xtradb (http://www.percona.com) 1.0.17-12.5 started; log sequence number 1660436

140429 18:28:23  innodb: shutdown completed; log sequence number 1660436

shutting down mysql...                                     [  ok  ]

starting mysql.....                                        [  ok  ]

執行成功後,檢查發現test資料庫已成功恢複。

四、 innobackupex使用

        前面提到,innobackupex可同時備份innodb和myisam引擎表,是以通常都直接使用innobackupex。需要注意的是my.cnf中必須加上datadir這個參數,因為要根據它來定位innodb引擎的資料檔案位置。

innobackupex也包含一系列參數,可通過innobackupex --help指令檢視,此處不逐一說明了。

下面我們通過一個完整的示例來示範其用法,如下:

(1)  備份

[root@db xtrabak]# more backup.sh 

log=innobackupex_`date +%f`.log

str=bak_`date +%f`

innobackupex --user=root --password=root123 --defaults-file=/etc/my.cnf --stream=tar /data/xtrabak/$str/ 2&gt;/data/xtrabak/$log | gzip&gt;/data/xtrabak/$str/base.tar.gz

echo "backup end" `date`

cp /etc/my.cnf /data/xtrabak/my_`date +%f`.cnf

--執行腳本:

[root@db xtrabak]# sh backup.sh 

backup begin wed apr 30 16:15:02 cst 2014

backup end wed apr 30 16:15:27 cst 2014

[root@db xtrabak]# cd bak_2014-04-30/

[root@db bak_2014-04-30]# ls

base.tar.gz

執行完成後,生成備份檔案的壓縮包

(2)  增量日志備份

由于資料庫不停的對外提供服務,備份之後的操作會記錄到binlong日志檔案中,是以我們還應備份後續的日志檔案。

此處删除幾張表,并切換日志以模拟真實環境,備份完整的binlog日志檔案;然後關閉資料庫,删除資料庫所有檔案,以便模拟故障。

--腳本内容(binlog備份到遠端機器):

[root@db xtrabak]# more binlog_bak.sh 

cd /var/lib/

date=`date -d ‘-1 hour‘ +%y%m%d%h00`

touch -t "${date}" starttemp

echo "$date"

umount /mnt_log&gt;/dev/null 2&gt;&amp;1

mount -t nfs 192.168.3.108:/logcenter /mnt_log

find /var/lib/mysql/mysql-bin.* -newer starttemp|xargs -i {} cp -p {} /mnt_log/mysql-binlog/192.168.3.28/

# umount -t nfs /mnt_log

[root@db xtrabak]# more prepare.sh 

# 2014-04-30

service mysql stop

mkdir -p /data/xtrabak/prepare_`date +%f`/

tar -ixzvf /data/xtrabak/bak_`date +%f`/base.tar.gz -c /data/xtrabak/prepare_`date +%f`/

innobackupex --apply-log --user=root --defaults-file=/etc/my.cnf /data/xtrabak/prepare_`date +%f`/

innobackupex --copy-back --user=root --defaults-file=/etc/my.cnf /data/xtrabak/prepare_`date +%f`/

chown -r mysql:mysql /var/lib/mysql/

rm -rf /var/lib/mysql/xtrabackup_binlog_pos_innodb

--完全備份恢複後,通過binlog進行增量恢複

[root@db xtrabak]# mysqlbinlog --start-position="******" /data/log/mysql-bin.****** |mysql -uroot -p

注意:start-position的位置可通過解壓後的備份檔案檢視,如下:

[root@db xtrabak]# cd prepare_2014-04-30/

[root@db prepare_2014-04-30]# more xtrabackup_binlog_info 

mysql-bin.000047        1472

或者

[root@db prepare_2014-04-30]# more xtrabackup_binlog_pos_innodb 

./mysql-bin.000047      1472

成功恢複後,mysql即可正常使用。