MySQL 之XtraBackup全量增量熱備實踐

天府雲創發表於2017-04-12

一、前言

在日常的linux運維工作中,大資料量備份與還原,始終是個難點。關於mysql的備份和恢復,比較傳統的是用mysqldump工具,今天推薦另一個備份工具innobackupex。

innobackupex和mysqldump都可以對mysql進行熱備份的,mysqldump對mysql的innodb的備份可以使用single-transaction引數來開啟一個事務,利用innodb的mvcc來不進行鎖表進行熱備份,mysqldump備份是邏輯備份,備份出來的檔案是sql語句,所以備份和恢復的時候很慢,但是備份和恢復時候很清楚。當MYSQL資料超過10G時,用mysqldump來匯出備份就比較慢了,此種情況下用innobackupex這個工具就比mysqldump要快很多。利用它對mysql做全量和增量備份.

Percona XtraBackup可以說是一個相對完美的免費開源資料備份工具,是使用perl語言完成的指令碼工具,能夠非常快速地備份與恢復mysql資料庫,且支援線上熱備份(備份時不影響資料讀寫),此工具呼叫xtrabackup和tar4ibd工具,實現很多對效能要求並不高的任務和備份邏輯,可以說它是innodb熱備工具ibbackup的一個開源替代品。

XtraBackup是目前首選的備份方案之一

二、原理

1、MySQL主從同步原理

MySQL主從同步是在MySQL主從複製(Master-Slave Replication)基礎上實現的,通過設定在Master MySQL上的binlog(使其處於開啟狀態),Slave MySQL上通過一個I/O執行緒從Master MySQL上讀取binlog,然後傳輸到Slave MySQL的中繼日誌中,然後Slave MySQL的SQL執行緒從中繼日誌中讀取中繼日誌,然後應用到Slave MySQL的資料庫中。這樣實現了主從資料同步功能。

2、XtraBackup備份原理

innobackupex在後臺執行緒不斷追蹤InnoDB的日誌檔案,然後複製InnoDB的資料檔案。資料檔案複製完成之後,日誌的複製執行緒也會結束。這樣就得到了不在同一時間點的資料副本和開始備份以後的事務日誌。完成上面的步驟之後,就可以使用InnoDB崩潰恢復程式碼執行事務日誌(redo log),以達到資料的一致性。

3、備份的兩個過程

backup,備份階段,追蹤事務日誌和複製資料檔案(物理備份)。

preparing,重放事務日誌,使所有的資料處於同一個時間點,達到一致性狀態。

4、XtraBackup的優點

1、可以快速可靠的完成資料備份(複製資料檔案和追蹤事務日誌)

2、資料備份過程中不會中斷事務的處理(熱備份)

3、節約磁碟空間和網路頻寬

4、自動完成備份鑑定

5、因更快的恢復時間而提高線上時間

5、Xtrabackup的兩個工具

1)xtrabackup :只能用於熱備份innodb,xtradb兩種資料引擎表的工具,不能備份其他表。

2)innobackupex:是一個對xtrabackup封裝的perl指令碼,提供了用於myisam(會鎖表)和innodb引擎,及混合使用引擎備份的能力。主要是為了方便同時備份InnoDB和MyISAM引擎的表,但在處理myisam時需要加一個讀鎖。並且加入了一些使用的選項。如slave-info可以記錄備份恢 復後,作為slave需要的一些資訊,根據這些資訊,可以很方便的利用備份來重做slave。 innobackupex比xtarbackup有更強的功能,它整合了xtrabackup和其他的一些功能,它不但可以全量備份/恢復,還可以基於時間的增量備份與恢復。innobackupex同時支援innodb,myisam。

6、Xtrabackup可以做什麼

1)線上(熱)備份整個庫的InnoDB, XtraDB表

2)在xtrabackup的上一次整庫備份基礎上做增量備份(innodb only)

3)以流的形式產生備份,可以直接儲存到遠端機器上(本機硬碟空間不足時很有用)

MySQL資料庫本身提供的工具並不支援真正的增量備份,二進位制日誌恢復是point-in-time(時間點)的恢復而不是增量備份。

7、Xtrabackup工具工作原理

支援對InnoDB儲存引擎的增量備份

1)首先完成一個完全備份,並記錄下此時檢查點的LSN(Log Sequence Number)。

2)在進行增量備份時,比較表空間中每個頁的LSN是否大於上次備份時的LSN,如果是,則備份該頁,同時記錄當前檢查點的LSN。首先,在logfile中找到並記錄最後一個checkpoint(“last checkpoint LSN”),然後開始從LSN的位置開始拷貝InnoDB的logfile到xtrabackup_logfile;接著,開始拷貝全部的資料檔案.ibd;在拷貝全部資料檔案結束之後,才停止拷貝logfile。因為logfile裡面記錄全部的資料修改情況,所以,即時在備份過程中資料檔案被修改過了,恢復時仍然能夠通過解析xtrabackup_logfile保持資料的一致。

8、innobackupex備份mysql資料的流程

innobackupex首先呼叫xtrabackup來備份innodb資料檔案,當xtrabackup完成後,innobackupex就檢視檔案xtrabackup_suspended ;然後執行“FLUSH TABLES WITH READ LOCK”來備份其他的檔案。

9、innobackupex恢復mysql資料的流程

innobackupex首先讀取my.cnf,檢視變數(datadir,innodb_data_home_dir,innodb_data_file_path,innodb_log_group_home_dir)對應的目錄是存在,確定相關目錄存在後,然後先copy myisam表和索引,然後在copy innodb的表、索引和日誌。

10、innobackupex備份和恢復的工作原理

(1)備份的工作原理

如果在程式啟動階段未指定模式,innobackupex將會預設以備份模式啟動。預設情況下,此指令碼以–suspend-at-end選項啟動xtrabackup,然後xtrabackup程式開始拷貝InnoDB資料檔案。當xtrabackup程式執行結束,innobackupex將會發現xtrabackup建立了xtrabackup_suspended_2檔案,然後執行FLUSH TABLES WITH READ LOCK,此語句對所有的資料庫表加讀鎖。然後開始拷貝其他型別的檔案。

如果–ibbackup未指定,innobackupex將會自行嘗試確定使用的xtrabackup的binary。其確定binary的邏輯如下:首先判斷備份目錄中xtrabackup_binary檔案是否存在,如果存在,此指令碼將會依據此檔案確定使用的xtrabackup binary。否則,指令碼將會嘗試連線database server,通過server版本確定binary。 如果連線無法建立,xtrabackup將會失敗,需要自行指定binary檔案。

在binary被確定後,將會檢查到資料庫server的連線是否可以建立。其執行邏輯是:建立連線、執行query、關閉連線。若一切正常,xtrabackup將以子程式的方式啟動。

FLUSH TABLES WITH READ LOCK是為了備份MyISAM和其他非InnoDB型別的表,此語句在xtrabackup已經備份InnoDB資料和日誌檔案後執行。在這之後,將會備份 .frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV, .par, and .opt 型別的檔案。

當所有上述檔案備份完成後,innobackupex指令碼將會恢復xtrabackup的執行,等待其備份上述邏輯執行過程中生成的事務日誌檔案。接下來,表被解鎖,slave被啟動,到server的連線被關閉。接下來,指令碼會刪掉xtrabackup_suspended_2檔案,允許xtrabackup程式退出。

(2)恢復的工作原理 為了恢復一個備份,innobackupex需要以–copy-back選項啟動。

innobackupex將會首先通過my.cnf檔案讀取如下變數:datadir, innodb_data_home_dir, innodb_data_file_path, innodb_log_group_home_dir,並確定這些目錄存在。

接下來,此指令碼將會首先拷貝MyISAM表、索引檔案、其他型別的檔案(如:.frm, .MRG, .MYD, .MYI, .TRG, .TRN, .ARM, .ARZ, .CSM, .CSV, par and .opt files),接下來拷貝InnoDB表資料檔案,最後拷貝日誌檔案。

拷貝執行時將會保留檔案屬性,在使用備份檔案啟動MySQL前,可能需要更改檔案的owener(如從拷貝檔案的user更改到mysql使用者)。

三、配置

1、準備工作

#系統環境

[root@master tools]# cat /etc/redhat-release 
CentOS release 6.8 (Final)
[root@master tools]# uname -r
2.6.32-642.el6.x86_64

#主資料庫版本

[root@master ~]# mysql -V
mysql  Ver 14.14 Distrib 5.5.32, for Linux (x86_64) using readline 5.1

#檢查資料庫引擎

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
8 rows in set (0.00 sec)

#主從資料庫同步注意點 [mysqld]

#主從之間的id不能相同 server-id

#啟用二進位制日誌 log-bin

#一般在從庫開啟(可選) read_only #推薦使用InnoDB並做好相關配置

#檢查主從資料庫狀態

[root@master ~]# mysql -e "show global variables like 'server_id';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 241   |
+---------------+-------+
[root@slave01 ~]# mysql -e "show global variables like 'server_id';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 242   |
+---------------+-------+

2、安裝percona-xtrabackup

官網安裝包地址 – https://www.percona.com/downloads/XtraBackup/LATEST/

1)原始碼安裝Xtrabackup

將原始碼包下載到/usr/local/src下

原始碼包下載

cd /usr/local/src

yum -y install cmake gcc gcc-c++ libaio libaio-devel automake autoconf bzr bison libtool  zlib-devel libgcrypt-devel  libcurl-devel  crypt*  libgcrypt* python-sphinx openssl   imake libxml2-devel expat-devel   ncurses5-devel ncurses-devle   vim-common  libgpg-error-devel   libidn-devel perl-DBI  perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL 

wget http://www.percona.com/downloads/XtraBackup/XtraBackup-2.1.9/source/percona-xtrabackup-2.1.9.tar.gz

tar -zvxf percona-xtrabackup-2.1.9.tar.gz

cd percona-xtrabackup-2.1.9


[root@master percona-xtrabackup-2.1.9]# ./utils/build.sh     //執行該安裝指令碼,會出現下面資訊
Build an xtrabackup binary against the specified InnoDB flavor.

Usage: build.sh CODEBASE
where CODEBASE can be one of the following values or aliases:
  innodb51         | plugin                build against InnoDB plugin in MySQL 5.1
  innodb55         | 5.5                   build against InnoDB in MySQL 5.5
  innodb56         | 5.6,xtradb56,         build against InnoDB in MySQL 5.6
                   | mariadb100,galera56
  xtradb51         | xtradb,mariadb51      build against Percona Server with XtraDB 5.1
                   | mariadb52,mariadb53
  xtradb55         | galera55,mariadb55    build against Percona Server with XtraDB 5.5

根據上面提示和你使用的儲存引擎及版本,選擇相應的引數即可。因為我用的是MySQL 5.5版本,所以執行如下語句安裝:

[root@master percona-xtrabackup-2.1.9]# ./utils/build.sh innodb55

以上語句執行成功後,表示安裝完成。

最後,把生成的二進位制檔案拷貝到一個自定義目錄下(本例中為/home/mysql/admin/bin/percona-xtrabackup-2.1.9),並把該目錄放到環境變數PATH中。

mkdir -p /home/mysql/admin/bin/percona-xtrabackup-2.1.9/
cp ./innobackupex /home/mysql/admin/bin/percona-xtrabackup-2.1.9/
mv /usr/local/src/percona-xtrabackup-2.1.9/src/xtrabackup_innodb55 xtrabackup_55 
cp /usr/local/src/percona-xtrabackup-2.1.9/src/xtrabackup_55 /usr/local/src/percona-xtrabackup-2.1.9/src/xbstream  /home/mysql/admin/bin/percona-xtrabackup-2.1.9/

vim /etc/profile

export PATH=$PATH:/home/mysql/admin/bin/percona-xtrabackup-2.1.9/

重新整理profile並測試下innobackupex是否正常使用

source /etc/profile

測試下innobackupex是否正常使用

innobackupex --help

3、全量備份和恢復

1)全量備份操作

執行下面語句進行全備: mysql的安裝目錄是/application/mysql/ mysql的配置檔案路徑/etc/my.cnf 全量備份後的資料存放目錄是/backup/mysql/data

mkdir -p /backup/mysql/data/
innobackupex --defaults-file=/etc/my.cnf --user=root /backup/mysql/data/
170404 12:46:29  innobackupex: Waiting for log copying to finish

xtrabackup: The latest check point (for incremental): '1639325'
xtrabackup: Stopping log copying thread.
.>> log scanned up to (1639325)

xtrabackup: Creating suspend file '/backup/mysql/data/2017-04-04_12-46-24/xtrabackup_log_copied' with pid '21223'
xtrabackup: Transaction log of lsn (1639325) to (1639325) was copied.
170404 12:46:30  innobackupex: All tables unlocked

innobackupex: Backup created in directory '/backup/mysql/data/2017-04-04_12-46-24'
innobackupex: MySQL binlog position: filename 'mysql-bin.000019', position 967
170404 12:46:30  innobackupex: Connection to database server closed
170404 12:46:30  innobackupex: completed OK!

出現上面的資訊,表示備份已經ok。

上面執行的備份語句會將mysql資料檔案(即由my.cnf裡的變數datadir指定)拷貝至備份目錄下(/backup/mysql/data)

注意:如果不指定–defaults-file,預設值為/etc/my.cnf。 備份成功後,將在備份目錄下建立一個時間戳目錄(本例建立的目錄為/backup/mysql/data/2017-04-04_12-46-24),在該目錄下存放備份檔案。

[root@master data]# ll /backup/mysql/data/
總用量 4
drwxr-xr-x 6 root root 4096 44 16:56 2017-04-04_16-56-35
[root@master data]# ll 2017-04-04_16-56-35/
總用量 18468
-rw-r--r-- 1 root root      188 44 16:56 backup-my.cnf
-rw-r----- 1 root root 18874368 44 16:56 ibdata1
drwxr-xr-x 2 root root     4096 44 16:56 mysql
drwxr-xr-x 2 root root     4096 44 16:56 performance_schema
drwxr-xr-x 2 root root     4096 44 16:56 test
-rw-r--r-- 1 root root       13 44 16:56 xtrabackup_binary
-rw-r--r-- 1 root root       23 44 16:56 xtrabackup_binlog_info
-rw-r----- 1 root root       89 44 16:56 xtrabackup_checkpoints
-rw-r----- 1 root root     2560 44 16:56 xtrabackup_logfile
drwxr-xr-x 2 root root     4096 44 16:56 xtra_test

還可以在遠端進行全量備份,命令如下:

innobackupex --defaults-file=/etc/my.cnf --user=root  --host=127.0.0.1 --parallel=2 --throttle=200 /backup/mysql/data 2>/backup/mysql/data/bak.log 1>/backup/mysql/data/`data +%Y-%m-%d_%H-%M%S`

引數解釋:

--user=root             備份操作使用者名稱,一般都是root使用者 

--host=127.0.0.1            主機ip,本地可以不加(適用於遠端備份)。注意要提前在mysql中授予連線的許可權,最好備份前先測試用命令中的使用者名稱、密碼和host能否正常連線mysql。

--parallel=2 --throttle=200      並行個數,根據主機配置選擇合適的,預設是1個,多個可以加快備份速度。

/backup/mysql/data            備份存放的目錄

2>/backup/mysql/data/bak.log       備份日誌,將備份過程中的輸出資訊重定向到bak.log

這種備份跟上面相比,備份成功後,不會自動在備份目錄下建立一個時間戳目錄,需要如上命令中自己定義。
[root@master src]# ll /backup/mysql/data/
總用量 8
drwxr-xr-x 6 root root 4096 44 12:46 2017-04-04_12-46-24
-rw-r--r-- 1 root root  106 44 12:57 bak.log    //備份資訊都記錄在這個日誌裡,如果備份失敗,可以到這裡日誌裡查詢

2)全量備份後的恢復操作

[root@master data]# mysql

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| xtra_test          |
+--------------------+
5 rows in set (0.09 sec)

mysql> use xtra_test;
Database changed
mysql> show tables;
+---------------------+
| Tables_in_xtra_test |
+---------------------+
| I                   |
| M                   |
+---------------------+
2 rows in set (0.04 sec)


mysql> drop database xtra_test;
Query OK, 2 rows affected (0.34 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

注意:恢復之前

1)要先關閉資料庫

2)要刪除資料檔案和日誌檔案(也可以mv移到別的地方,只要確保清空mysql資料存放目錄就行)

[root@master data]# ps -ef|grep mysqld
root     10929     1  0 10:32 pts/0    00:00:00 /bin/sh /application/mysql/bin/mysqld_safe --datadir=/application/mysql/data --pid-file=/application/mysql/data/master.pid
mysql    11227 10929  0 10:32 pts/0    00:00:14 /application/mysql/bin/mysqld --basedir=/application/mysql --datadir=/application/mysql/data --plugin-dir=/application/mysql/lib/plugin --user=mysql --log-error=/application/mysql/data/master.err --pid-file=/application/mysql/data/master.pid --port=3306
root     21514  1896  0 13:55 pts/0    00:00:00 grep mysqld

由上面可以看出mysql的資料和日誌存放目錄是/application/mysql/data

[root@master data]# service mysqld stop
Shutting down MySQL.... SUCCESS!

[root@master data]# mv  /application/mysql/data/* /tmp/

[root@master data]# ls /application/mysql/data/
[root@master data]#
[root@master data]# innobackupex --defaults-file=/etc/my.cnf --user=root --use-memory=1G --apply-log /backup/mysql/data/2017-04-04_13-04-05/

[root@master data]# innobackupex --defaults-file=/etc/my.cnf --user=root --copy-back /backup/mysql/data/2017-04-04_13-04-05/

[root@master ~]# chown -R mysql.mysql /application/mysql/data/

可能報錯:

sh: xtrabackup: command not found
innobackupex: Error: no 'mysqld' group in MySQL options at /home/mysql/admin/bin/percona-xtrabackup-2.1.9/innobackupex line 4350.

解決:將xtrabackup_55複製成xtrabackup即可

[root@master src]# ls /home/mysql/admin/bin/percona-xtrabackup-2.1.9/
innobackupex  xbstream  xtrabackup_55  xtrabackup_innodb55

[root@master src]# cd /home/mysql/admin/bin/percona-xtrabackup-2.1.9/

[root@master percona-xtrabackup-2.1.9]# cp xtrabackup_55 xtrabackup

[root@master percona-xtrabackup-2.1.9]# ls
innobackupex  xbstream  xtrabackup  xtrabackup_55  xtrabackup_innodb55

檢驗:執行之後就OK了

[root@master percona-xtrabackup-2.1.9]# innobackupex --defaults-file=/etc/my.cnf --user=root --copy-back /backup/mysql/data/2017-04-04_13-04-05/


innobackupex: Copying '/backup/mysql/data/2017-04-04_13-04-05/ib_logfile1' to '/application/mysql/data/ib_logfile1'
innobackupex: Copying '/backup/mysql/data/2017-04-04_13-04-05/ib_logfile0' to '/application/mysql/data/ib_logfile0'
innobackupex: Finished copying back files.

170404 14:24:07  innobackupex: completed OK!

出現上面的資訊,說明資料恢復成功了!!

從上面的恢復操作可以看出,執行恢復分為兩個步驟:

1)第一步恢復步驟是應用日誌(apply-log),為了加快速度,一般建議設定–use-memory(如果系統記憶體充足,可以使用加大記憶體進行備份 ),這個步驟完成之後,目錄/backup/mysql/data/2017-04-04_13-04-05/下的備份檔案已經準備就緒。

2)第二步恢復步驟是拷貝檔案(copy-back),即把備份檔案拷貝至原資料目錄下。

最後,啟動mysql,檢視資料是否恢復回來了

[root@master ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS! 

[root@master ~]# mysql

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| xtra_test          |
+--------------------+
5 rows in set (0.00 sec)

mysql> use xtra_test;
Database changed
mysql> show tables;
+---------------------+
| Tables_in_xtra_test |
+---------------------+
| I                   |
| M                   |
+---------------------+
2 rows in set (0.00 sec)

4、增量備份和恢復

特別注意:

innobackupex 增量備份僅針對InnoDB這類支援事務的引擎,對於MyISAM等引擎,則仍然是全備。

1)增量備份操作

增量備份需要基於全量備份

先假設我們已經有了一個全量備份(如上面的/backup/mysql/data/2017-04-04_16-56-35),我們需要在該全量備份的基礎上做第一次增量備份。

[root@master ~]# innobackupex --defaults-file=/etc/my.cnf --user=root  --incremental-basedir=/backup/mysql/data/2017-04-04_16-56-35/ --incremental /backup/mysql/data

其中:

–incremental-basedir 指向全量備份目錄 –incremental 指向增量備份的目錄

上面語句執行成功之後,會在–incremental執行的目錄下建立一個時間戳子目錄(本例中為:/backup/mysql/data/2017-04-04_14-37-24),在該目錄下存放著增量備份的所有檔案。

[root@master data]# ll
總用量 8
drwxr-xr-x 6 root root 4096 44 16:56 2017-04-04_16-56-35   //全量備份目錄
drwxr-xr-x 6 root root 4096 44 16:59 2017-04-04_16-58-58  //增量備份目錄

在備份目錄下,有一個檔案xtrabackup_checkpoints記錄著備份資訊,其中可以查出

1)全量備份的資訊如下:

[root@master data]# cd /backup/mysql/data/2017-04-04_16-56-35/
[root@master 2017-04-04_16-56-35]# cat xtrabackup_checkpoints 
backup_type = full-backuped
from_lsn = 0
to_lsn = 1639436
last_lsn = 1639436
compact = 0

2)基於以上全量備份的增量備份的資訊如下:

[root@master data]# cd /backup/mysql/data/2017-04-04_16-58-58/
[root@master 2017-04-04_16-58-58]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1639436
to_lsn = 1639436
last_lsn = 1639436
compact = 0

從上面可以看出,增量備份的from_lsn正好等於全備的to_lsn。

那麼,我們是否可以在增量備份的基礎上再做增量備份呢?

答案是肯定的,只要把–incremental-basedir執行上一次增量備份的目錄即可,如下所示:

[root@master data]# innobackupex --defaults-file=/etc/my.cnf --user=root --incremental-basedir=/backup/mysql/data/2017-04-04_16-58-58/ --incremental /backup/mysql/data 

[root@master ~]# ll /backup/mysql/data/
總用量 12
drwxr-xr-x 6 root root 4096 44 16:56 2017-04-04_16-56-35    //全量備份目錄
drwxr-xr-x 6 root root 4096 44 16:59 2017-04-04_16-58-58    //增量備份目錄1
drwxr-xr-x 6 root root 4096 44 17:02 2017-04-04_17-02-35  //增量備份目錄2

它的trabackup_checkpoints記錄著備份資訊如下:

[root@master ~]# cd /backup/mysql/data/2017-04-04_17-02-35/
[root@master 2017-04-04_17-02-35]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1639436
to_lsn = 1639436
last_lsn = 1639436
compact = 0

可以看到,第二次增量備份的from_lsn是從上一次增量備份的to_lsn開始的

2)增量備份後的恢復操作

增量備份的恢復要比全量備份複雜很多,增量備份與全量備份有著一些不同,尤其要注意的是:

1)需要在每個備份(包括完全和各個增量備份)上,將已經提交的事務進行“重放”。“重放”之後,所有的備份資料將合併到完全備份上。

2)基於所有的備份將未提交的事務進行“回滾”。於是,操作就變成了:不能回滾,因為有可能第一次備份時候沒提交,在增量中已經成功提交

第一步是在所有備份目錄下重做已提交的日誌(注意備份目錄路徑要跟全路徑)

其中:

一定要全路徑

BASE-DIR 是指全量備份的目錄

INCREMENTAL-DIR-1 是指第一次增量備份的目錄

INCREMENTAL-DIR-2 是指第二次增量備份的目錄,以此類推。

這裡要注意的是:

1)最後一步的增量備份並沒有–redo-only選項!回滾進行崩潰恢復過程

2)可以使用–use_memory提高效能。

以上語句執行成功之後,最終資料在BASE-DIR(即全量目錄)下,其實增量備份就是把增量目錄下的資料,整合到全變數目錄下,然後在進行,全資料量的還原。

第一步完成之後,我們開始下面關鍵的第二步,即拷貝檔案,進行全部還原!注意:必須先停止mysql資料庫,然後清空資料庫目錄(這裡是指/data/mysql/data)下的檔案。

4)innobackupex –copy-back BASE-DIR

同樣地,拷貝結束之後,記得檢查下資料目錄(這裡指/data/mysql/data)的許可權是否正確(修改成mysql:mysql),然後再重啟mysql。

接下來進行案例說明:

假設我們已經有了一個全量備份2017-04-04_16-56-35 刪除在上面測試建立的兩個增量備份

[root@master ~]# cd /backup/mysql/data/

[root@master data]# ll
drwxr-xr-x 6 root root 4096 44 17:08 2017-04-04_16-56-35
drwxr-xr-x 6 root root 4096 44 17:08 2017-04-04_16-58-58
drwxr-xr-x 6 root root 4096 44 17:08 2017-04-04_17-02-35

[root@master data]# rm -fr 2017-04-04_16-58-58 2017-04-04_17-02-35


[root@master data]# ll
drwxr-xr-x 6 root root 4096 44 17:08 2017-04-04_16-56-35

假設在全量備份後,mysql資料庫中又有新資料寫入

[root@master data]# mysql

mysql> create database ceshi;
Query OK, 1 row affected (0.00 sec)

mysql> use ceshi
Database changed
mysql> create table test1(
    -> id int3,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.26 sec)

mysql> insert into test1 values(1,"chenbaojia");
Query OK, 1 row affected (0.05 sec)

mysql> select * from test1;
+------+------------+
| id   | name       |
+------+------------+
|    1 | chenbaojia |
+------+------------+
1 row in set (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| ceshi              |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

然後進行一次增量備份:

[root@master data]# innobackupex --defaults-file=/etc/my.cnf --user=root --incremental-basedir=/backup/mysql/data/2017-04-04_16-56-35/ --incremental /backup/mysql/data/


[root@master data]# ll
總用量 8
drwxr-xr-x 6 root root 4096 44 17:08 2017-04-04_16-56-35       //全量備份目錄
drwxr-xr-x 6 root root 4096 44 17:28 2017-04-04_17-28-14        //增量備份目錄

接著再在mysql資料庫中寫入新資料

[root@master data]# mysql

mysql> use ceshi;
Database changed

mysql> insert into test1  values(2,"pelosi");
Query OK, 1 row affected (0.11 sec)

mysql> insert into test1 values(3,"hiofo");
Query OK, 1 row affected (0.06 sec)

mysql> insert into test1 values(4,"mac");
Query OK, 1 row affected (0.09 sec)

mysql> select * from test1;
+------+------------+
| id   | name       |
+------+------------+
|    1 | chenbaojia |
|    2 | pelosi     |
|    3 | hiofo      |
|    4 | mac        |
+------+------------+
4 rows in set (0.00 sec)

接著在增量的基礎上再進行一次增量備份

–incremental-basedi 要寫上次最後增量備份的目錄

[root@master ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --incremental-basedir=/backup/mysql/data/2017-04-04_17-28-14/ --incremental /backup/mysql/data

[root@master ~]# ll /backup/mysql/data/
總用量 12
drwxr-xr-x 6 root root 4096 44 17:08 2017-04-04_16-56-35      //全量備份目錄
drwxr-xr-x 6 root root 4096 44 17:28 2017-04-04_17-28-14      //全量備份目錄
drwxr-xr-x 6 root root 4096 44 17:38 2017-04-04_17-37-58      //全量備份目錄

現在刪除資料庫ceshi 、 test

[root@master ~]# mysql


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| ceshi              |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

mysql> drop  database ceshi;
Query OK, 1 row affected (0.07 sec)

mysql> drop database test;
Query OK, 0 rows affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

接下來就開始進行資料恢復操作:

先恢復應用日誌(注意最後一個不需要加–redo-only引數)

[root@master ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --apply-log --redo-only /backup/mysql/data/2017-04-04_16-56-35/

[root@master ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --apply-log --redo-only /backup/mysql/data/2017-04-04_16-56-35/ --incremental-dir=/backup/mysql/data/2017-04-04_17-28-14/

[root@master ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --apply-log /backup/mysql/data/2017-04-04_16-56-35/ --incremental-dir=/backup/mysql/data/2017-04-04_17-37-58/

到此,恢復資料工作還沒有結束!還有最重要的一個環節,就是把增量目錄下的資料整合到全量備份目錄下,然後再進行一次全量還原。

停止mysql資料庫,並清空資料目錄

[root@master ~]# /etc/init.d/mysqld stop
Shutting down MySQL. SUCCESS! 
[root@master ~]# rm -fr /application/mysql/data/*

最後拷貝檔案,並驗證資料目錄的許可權

[root@master ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --copy-back /backup/mysql/data/2017-04-04_16-56-35/

[root@master ~]# chown -R mysql.mysql /application/mysql/data/*

[root@master ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[root@master ~]# mysql

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| ceshi              |
| mysql              |
| performance_schema |
| test               |
| xtra_test          |
+--------------------+
6 rows in set (0.00 sec)

mysql> select * from  ceshi.test1;
+------+------------+
| id   | name       |
+------+------------+
|    1 | chenbaojia |
|    2 | pelosi     |
|    3 | hiofo      |
|    4 | mac        |
+------+------------+
4 rows in set (0.00 sec)

另外注意: 上面在做備份的時候,將備份目錄和增量目錄都放在了同一個目錄路徑下,其實推薦放在不同的路徑下,方便管理!比如:

/backup/mysql/data/full 存放全量備份目錄

/backup/mysql/data/daily1 存放第一次增量備份目錄

/backup/mysql/data/daily2 存放第二次增量目錄

以此類推

在恢復的時候,注意命令中的路徑要跟對!

5、innobackupex 引數

xtrabackup命令只備份資料檔案,並不備份資料表結構(.frm),所以使用xtrabackup恢復的時候必須有對應表結構檔案(.frm)。用innobackupex命令,此命令相當於冷備份,複製資料目錄的索引,資料,結構檔案,但會有短暫的鎖表(時間依賴於MyISAM大小)。

innobackupex 常用引數說明 –defaults-file 同xtrabackup的–defaults-file引數

–apply-log 對xtrabackup的–prepare引數的封裝

–copy-back 做資料恢復時將備份資料檔案拷貝到MySQL伺服器的datadir ;

–remote-host=HOSTNAME 通過ssh將備份資料儲存到程式伺服器上;

–stream=[tar] 備 份檔案輸出格式, tar時使用tar4ibd , 該檔案可在XtarBackup binary檔案中獲得.如果備份時有指定–stream=tar, 則tar4ibd檔案所處目錄一定要在$PATH中(因為使用的是tar4ibd去壓縮, 在XtraBackup的binary包中可獲得該檔案)。 在 使用引數stream=tar備份的時候,你的xtrabackup_logfile可能會臨時放在/tmp目錄下,如果你備份的時候併發寫入較大的話 xtrabackup_logfile可能會很大(5G+),很可能會撐滿你的/tmp目錄,可以通過引數–tmpdir指定目錄來解決這個問題。

–tmpdir=DIRECTORY 當有指定–remote-host or –stream時, 事務日誌臨時儲存的目錄, 預設採用MySQL配置檔案中所指定的臨時目錄tmpdir

–redo-only –apply-log組, 強制備份日誌時只redo ,跳過rollback。這在做增量備份時非常必要。

–use-memory=# 該引數在prepare的時候使用,控制prepare時innodb例項使用的記憶體量

–throttle=IOS 同xtrabackup的–throttle引數

–sleep=是給ibbackup使用的,指定每備份1M資料,過程停止拷貝多少毫秒,也是為了在備份時儘量減小對正常業務的影響,具體可以檢視ibbackup的手冊 ;

–compress[=LEVEL] 對備份資料迚行壓縮,僅支援ibbackup,xtrabackup還沒有實現;

–include=REGEXP 對 xtrabackup引數–tables的封裝,也支援ibbackup。備份包含的庫表,例如:–include=”test.“,意思是要備份 test庫中所有的表。如果需要全備份,則省略這個引數;如果需要備份test庫下的2個表:test1和test2,則寫 成:–include=”test.test1|test.test2″。也可以使用萬用字元,如:–include=”test.test“。

–databases=LIST 列出需要備份的databases,如果沒有指定該引數,所有包含MyISAM和InnoDB表的database都會被備份;

–uncompress 解壓備份的資料檔案,支援ibbackup,xtrabackup還沒有實現該功能;

–slave-info, 備 份從庫, 加上–slave-info備份目錄下會多生成一個xtrabackup_slave_info 檔案, 這裡會儲存主日誌檔案以及偏移, 檔案內容類似於:CHANGE MASTER TO MASTER_LOG_FILE=”, MASTER_LOG_POS=0

–socket=SOCKET 指定mysql.sock所在位置,以便備份程式登入mysql.

更多引數見:http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/innobackupex_option_reference.html

三、innobackupex全量、增量備份指令碼

可以根據自己線上資料庫情況,編寫全量和增量備份指令碼,然後結合crontab設定計劃執行。

比如:每週日的1:00進行全量備份,每週1-6的1:00進行增量備份。

還可以在指令碼里編寫郵件通知資訊(可以用mail或sendemail)

四、FAQ

1、可能報錯1

Can't locate Time/HiRes.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /home/mysql/admin/bin/percona-xtrabackup-2.1.9/innobackupex line 23.
BEGIN failed--compilation aborted at /home/mysql/admin/bin/percona-xtrabackup-2.1.9/innobackupex line 23.

解決方案:

.pm實際上是Perl的包,只需安裝perl-Time-HiRes即可:

[root@test-huanqiu percona-xtrabackup-2.1.9]# yum install -y perl-Time-HiRes

2、可能報錯2

Can't locate DBI.pm in @INC (@INC contains: /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.8.8 /usr/lib/perl5/site_perl /usr/lib64/perl5/vendor_perl/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.8 /usr/lib/perl5/vendor_perl /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/5.8.8 .) at /usr/local/webserver/mysql5.1.57/bin/mysqlhotcopy line 25. 
BEGIN failed--compilation aborted at /usr/local/webserver/mysql5.1.57/bin/mysqlhotcopy line 25.

報錯原因:系統沒有按安裝DBI元件。

DBI(Database Interface)是perl連線資料庫的介面。其是perl連線資料庫的最優秀方法,他支援包括Orcal,Sybase,mysql,db2等絕大多數的資料庫。

解決辦法:

安裝DBI元件(Can’t locate DBI.pm in @INC-mysql介面)

或者單獨裝DBI、Data-ShowTable、DBD-mysql 三個元件

[root@test-huanqiu percona-xtrabackup-2.1.9]# yum -y install perl-DBD-MySQL

接著使用innobackupex命令測試是否正常

[root@test-huanqiu percona-xtrabackup-2.1.9]# innobackupex --help
Options:
--apply-log
Prepare a backup in BACKUP-DIR by applying the transaction log file
named "xtrabackup_logfile" located in the same directory. Also,
create new transaction logs. The InnoDB configuration is read from
the file "backup-my.cnf".

--compact
Create a compact backup with all secondary index pages omitted. This
option is passed directly to xtrabackup. See xtrabackup
documentation for details.

--compress
This option instructs xtrabackup to compress backup copies of InnoDB
data files. It is passed directly to the xtrabackup child process.
Try 'xtrabackup --help' for more details.

3、可能報錯3

161130 05:56:48 innobackupex: Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_file=/usr/local/mysql/my.cnf;mysql_read_default_group=xtrabackup' as 'root' (using password: YES).
innobackupex: Error: Failed to connect to MySQL server as DBD::mysql module is not installed at /home/mysql/admin/bin/percona-xtrabackup-2.1.9/innobackupex line 2956.

解決辦法:

[root@test-huanqiu ~]# yum -y install perl-DBD-MySQL.x86_64 
......
Package perl-DBD-MySQL-4.013-3.el6.x86_64 already installed and latest version                //發現本機已經安裝了

[root@test-huanqiu ~]# rpm -qa|grep perl-DBD-MySQL
perl-DBD-MySQL-4.013-3.el6.x86_64

發現本機已經安裝了最新版的perl-DBD-MYSQL了,但是仍然報出上面的錯誤!! 莫慌~~繼續下面的操作進行問題的解決

檢視mysql.so依賴的lib庫

[root@test-huanqiu ~]# ldd /usr/lib64/perl5/auto/DBD/mysql/mysql.so
linux-vdso.so.1 => (0x00007ffd291fc000)
libmysqlclient.so.16 => not found                                                   //這一項為通過檢查,缺失libmysqlclient.so.16庫導致
libz.so.1 => /lib64/libz.so.1 (0x00007f78ff9de000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f78ff7a7000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f78ff58e000)
libm.so.6 => /lib64/libm.so.6 (0x00007f78ff309000)
libssl.so.10 => /usr/lib64/libssl.so.10 (0x00007f78ff09d000)
libcrypto.so.10 => /usr/lib64/libcrypto.so.10 (0x00007f78fecb9000)
libc.so.6 => /lib64/libc.so.6 (0x00007f78fe924000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007f78fe721000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f78fe4dd000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f78fe1f5000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f78fdff1000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f78fddc5000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f78fdbc0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f78ffe1d000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f78fd9b5000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f78fd7b2000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f78fd597000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f78fd37a000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f78fd15a000)

以上結果說明缺少libmysqlclient.so.16這個二進位制包,找個官方原版的mysql的libmysqlclient.so.16替換了即可!

[root@test-huanqiu~]# find / -name libmysqlclient.so.16                                   //檢視本機並沒有libmysqlclient.so.16庫檔案

檢視mysql/lib下的libmysqlclinet.so庫檔案

[root@test-huanqiu~]# ll /usr/local/mysql/lib/
total 234596
-rw-r--r--. 1 mysql mysql 19520800 Nov 29 12:27 libmysqlclient.a
lrwxrwxrwx. 1 mysql mysql 16 Nov 29 12:34 libmysqlclient_r.a -> libmysqlclient.a
lrwxrwxrwx. 1 mysql mysql 17 Nov 29 12:34 libmysqlclient_r.so -> libmysqlclient.so
lrwxrwxrwx. 1 mysql mysql 20 Nov 29 12:34 libmysqlclient_r.so.18 -> libmysqlclient.so.18
lrwxrwxrwx. 1 mysql mysql 24 Nov 29 12:34 libmysqlclient_r.so.18.1.0 -> libmysqlclient.so.18.1.0
lrwxrwxrwx. 1 mysql mysql 20 Nov 29 12:34 libmysqlclient.so -> libmysqlclient.so.18
lrwxrwxrwx. 1 mysql mysql 24 Nov 29 12:34 libmysqlclient.so.18 -> libmysqlclient.so.18.1.0
-rwxr-xr-x. 1 mysql mysql 8858235 Nov 29 12:27 libmysqlclient.so.18.1.0
-rw-r--r--. 1 mysql mysql 211822074 Nov 29 12:34 libmysqld.a
-rw-r--r--. 1 mysql mysql 14270 Nov 29 12:27 libmysqlservices.a
drwxr-xr-x. 3 mysql mysql 4096 Nov 29 12:34 plugin

將mysql/lib/libmysqlclient.so.18.1.0庫檔案拷貝到/lib64下,拷貝後命名為libmysqlclient.so.16

[root@test-huanqiu~]# cp /usr/local/mysql/lib/libmysqlclient.so.18.1.0 /lib64/libmysqlclient.so.16

[root@test-huanqiu~]# cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/local/mysql/lib/ 
/lib64/
[root@test-huanqiu~]# ldconfig

最後解除安裝perl-DBD-MySQL,並重新安裝perl-DBD-MySQL
[root@test-huanqiu~]# rpm -qa|grep perl-DBD-MySQL
perl-DBD-MySQL-4.013-3.el6.x86_64
[root@test-huanqiu~]# rpm -e --nodeps perl-DBD-MySQL 
[root@test-huanqiu~]# rpm -qa|grep perl-DBD-MySQL
[root@test-huanqiu~]# yum -y install perl-DBD-MySQL

待重新安裝後,再次重新檢查mysql.so依賴的lib庫,發現已經都通過了

[root@test-huanqiu~]# ldd /usr/lib64/perl5/auto/DBD/mysql/mysql.so
linux-vdso.so.1 => (0x00007ffe3669b000)
libmysqlclient.so.16 => /usr/lib64/mysql/libmysqlclient.so.16 (0x00007f4af5c25000)
libz.so.1 => /lib64/libz.so.1 (0x00007f4af5a0f000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f4af57d7000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f4af55be000)
libm.so.6 => /lib64/libm.so.6 (0x00007f4af533a000)
libssl.so.10 => /usr/lib64/libssl.so.10 (0x00007f4af50cd000)
libcrypto.so.10 => /usr/lib64/libcrypto.so.10 (0x00007f4af4ce9000)
libc.so.6 => /lib64/libc.so.6 (0x00007f4af4955000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007f4af4751000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f4af450d000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f4af4226000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f4af4021000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f4af3df5000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f4af3bf1000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4af61d1000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f4af39e5000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f4af37e2000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f4af35c8000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4af33aa000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f4af318b000)

4、可能報錯4

sh: xtrabackup_56: command not found
innobackupex: Error: no 'mysqld' group in MySQL options at /home/mysql/admin/bin/percona-xtrabackup-2.1.9/innobackupex line 4350.

有可能是percona-xtrabackup編譯安裝後,在編譯目錄的src下存在xtrabackup_innodb55,只需要其更名為xtrabackup_55,然後拷貝到上面的/home/mysql/admin/bin/percona-xtrabackup-2.1.9/下即可!

相關文章