xtrabackup全備+增備MySQL數據庫實現方法

上一篇博客MySQL回滾到某一時刻數據的方法,說到了mysql沒有Oracle,DB2這種企業級數據庫常見的增量備份功能,只有類似於binlog的歸檔日誌。可以實現先恢復全備,再重做歸檔日誌進行回滾到之前任意時間點數據的功能。由於binlog是以事務爲單位,記錄了每條數據的時間信息,而且支持最好的ROW格式又格外佔空間,會導致一些數據量較大的數據庫的binlog也特別龐大,佔用特別巨大的存儲空間。一般最多也就保留幾天。而企業級數據庫往往要求能恢復到過去半年裏每天某個時間的數據。這往往就用到了Oracle,DB2的全備和增備功能。由於這兩個企業級數據庫的增備相當於一個快照,裏面不像歸檔日誌那樣包含時間信息,所以佔用空間小,特別適合長時間保存。雖然Mysql官方沒有提供增備的方法,但是一些第三方開源工具比如xtrabackup提供了這樣類似快照的方法。而且是基於innodb裏有關事務的特性,能做到強一致性,非常推薦。但是xtrabackup相對於企業級數據庫還是有一點缺點,就是無法根據全備增備和歸檔日誌回滾到之前某一時刻的數據。而在Oracle和DB2中,都可以先恢復全備,再逐個恢復增備,再重做歸檔日誌到某一具體時間。而xtrabackup的備份是無法和binlog相結合的。適合於進行主從初始化複製和保留歷史數據的功能,不太適合回滾。

下面簡單列一下xtrabackup的優點和不足

優點

1、備份非常快速和可靠

2、備份期間不會影響數據庫讀寫。這個是因爲xtrabackup結合innodb引擎的事務特性,不會像mysqldump那樣在備份期間進行鎖表,所以xtrabackup在備份時對數據庫性能影響非常小,在大數據庫備份時優點非常可觀。

3、可以備份到本地磁盤和網絡上

不足

1、不能結合binlog進行事務的重做,無法回滾到任意時刻

2、恢復的操作基本靠手動逐個恢復,不像Oracle一樣一行命令完成,但是同時提高了異地恢復的便捷性。


下面以實例介紹如何使用xtrabackup進行全備和增備。由於xtrabackup時percona的產品,所以這裏使用percona5.7.21數據庫爲例,安裝方法可以看我之前寫的一片博客 基於Docker的MYSQL PXC集羣搭建,由於進行full安裝,所以默認xtrabackup和percona pxc集羣數據庫都會被安裝上,減少了安裝過程的繁瑣。

大體過程如下

1、建庫建表插入數據

2、進行一次全備,並異地還原一次

3、再插入數據,進行一次增備

4、繼續插入數據,進行第二次增備

5、分別異地還原一次增備和二次增備的內容

首先我們啓動percona數據庫,建庫建表,插入兩條數據

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

mysql> create database dbtest;
Query OK, 1 row affected (0.12 sec)

mysql> use dbtest;
Database changed
mysql> create table table1 ( id int primary key, name varchar(40), birthday datetime);
Query OK, 0 rows affected (0.96 sec)

mysql> insert into table1 values (1,'befor_full1',NOW());
Query OK, 1 row affected (0.06 sec)

mysql> insert into table1 values (2,'befor_full2',NOW());
Query OK, 1 row affected (0.09 sec)

mysql> select * from table1;
+----+-------------+---------------------+
| id | name        | birthday            |
+----+-------------+---------------------+
|  1 | befor_full1 | 2018-06-10 01:31:54 |
|  2 | befor_full2 | 2018-06-10 01:32:00 |
+----+-------------+---------------------+
2 rows in set (0.00 sec)

下面開始全備,在這裏由於用到了innodb的特性,所以xtrabackup需要鏈接數據庫,所以就需要保證數據庫的正常運行,另外還需要給xtrabackup指定一個具有讀寫權限的用戶,這個用戶給root是完全可以的,但是在生產中我們很少會提供給別人root用戶的密碼,所以我們可以新建一個用戶。

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

然後我們退出sql界面,準備開始進行全備,這個操作可以使用系統用戶root,也可以用其他的系統用戶

$ xtrabackup --user=bkpuser --password=123456 --backup --target-dir=/home/full/

在全備中必須指定的參數是--user,也就是我們剛剛創建的bkpuser或者root,--password是該用戶的密碼,--target-dir就是我們本次備份生成的文件放置的目錄,如果你不寫--target-dir而是直接寫一個目錄,那麼xtrabackup會自動在你寫的目錄下面以時間日期格式建立一個新目錄,裏面放備份的文件,如果你寫了--target-dir那麼xtrabackup就不會新建子目錄,而是直接寫道你提供的目錄下。

另外有一些隱含參數,比如mysql的IP的端口還有socket位置什麼的,這些你都可以通過你本地的mysql配置文件來解決默認,加入--defaults-file=/etc/my.cnf這樣的參數即可。

另外你可以在全備的時候選擇--compress壓縮或者不壓縮,這裏我們先不壓縮,後續使用xz工具進行統一壓縮

xtrabackup --user=bkpuser --password=123456 --backup --target-dir=/home/full/
encryption: using gcrypt 1.6.5
180610 02:03:28  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/var/run/mysqld/mysqld.sock' as 'bkpuser'  (using password: YES).
180610 02:03:28  version_check Connected to MySQL server
180610 02:03:28  version_check Executing a version check against the server...
180610 02:03:28  version_check Done.
......
xtrabackup: Transaction log of lsn (2591133) to (2591158) was copied.
180610 02:03:47 completed OK!

備份完畢之後我們看一下有哪些文件

root@9f6505094522:/# ls -l /home/full/
total 12332
-rw-r----- 1 root root      487 Jun 10 02:03 backup-my.cnf
drwxr-x--- 2 root root     4096 Jun 10 02:03 dbtest
-rw-r----- 1 root root      352 Jun 10 02:03 ib_buffer_pool
-rw-r----- 1 root root 12582912 Jun 10 02:03 ibdata1
drwxr-x--- 2 root root     4096 Jun 10 02:03 mysql
drwxr-x--- 2 root root     4096 Jun 10 02:03 performance_schema
drwxr-x--- 2 root root    12288 Jun 10 02:03 sys
-rw-r----- 1 root root      113 Jun 10 02:03 xtrabackup_checkpoints
-rw-r----- 1 root root      455 Jun 10 02:03 xtrabackup_info
-rw-r----- 1 root root     2560 Jun 10 02:03 xtrabackup_logfile

然後我們打包壓縮一下,傳到其他服務器上進行異地恢復

cd /home
tar -Jcvf full.tar.xz full

壓縮之前爲26M,壓縮後爲279K,xz的壓縮率還是比較好,當然你也可以在備份的時候就選擇讓xtrabackup給你壓縮成qd格式,可以選擇多線程壓縮。

我們把full.tar.xz拷貝到新服務器的/home下面,然後解壓出來。

解壓出來之後我們就可以開始我們的恢復操作了。在恢復之前,首先我們要prepare一下,那麼什麼是prepare,爲什麼要prepare操作呢。簡單來說,你如果不prepare一下的話,那麼你恢復完之後是無法開啓數據庫的。因爲你在備份的時候由於innodb事務的控制,有可能在備份的時候有新的事務進來,而xtrabackup是不會影響事務讀寫的,所以備份出來的東西有很多未完成的事務在裏面,需要通過prepare將未完成的事務回滾或者其他操作。當你有增備的時候,你還需要通過prepare來把增備的數據添加到全備上再進行恢復,所以xtrabakcup手冊上很明確的指出,在恢復之前必須進行prepare操作,而且這個prepare操作對於全備和增備是不同的。

好在進行prepare操作並不需要mysql服務的參與,只要在安裝有xtrabackup的機器上即可進行。

xtrabackup --prepare --target-dir=/home/full

在只恢復全備的時候,只提供一個參數就行了,--target-dir,注意這個目錄是寫剛剛解壓出壓縮包的路徑,而不是你mysql表空間的路徑,這個操作可以使用系統用戶root,也可以用其他的系統用戶

# xtrabackup --prepare --target-dir=/home/full
encryption: using gcrypt 1.6.5
xtrabackup version 2.4.11 based on MySQL server 5.7.19 Linux (x86_64) (revision id: b4e0db5)
xtrabackup: cd to /home/full/
......
180610 02:17:51 completed OK!

prepare結束之後,我們就可以恢復數據庫了。xtrabackup恢復數據庫方法很特別,我們知道mysqldump出來的文件是一系列的sql語句,需要通過執行來達到恢復的效果。而xtrabackup非常簡單粗暴,直接通過把文件拷貝到你的mysql表空間目錄裏完成恢復,這樣做的好處就是比較快,我們知道複製文件的速度肯定比耗用CPU去解析sql然後瘋狂插入要好得多,但代價是要把你的mysql停止掉,然後刪掉原來表空間目錄下的所有文件。

首先,停止mysql

/etc/init.d/mysql stop
注意,備份的時候是要開着mysql服務,這樣才能鏈接innodb,但是prepare和恢復的時候,都推薦關掉mysql服務。

$ xtrabackup --copy-back --target-dir=/home/full/

這裏一般只需要提供--target-dir即可,這裏的目錄和上面prepare一樣,是填寫你備份解壓出來的路徑,而不是表空間的路徑。這裏有默認參數,其中這裏默認把你的表空間路徑指定爲/var/lib/mysql,如果你的表空間沒有放在這裏,那你需要指定你mysql配置文件my.cnf的位置。--defaults-file=/etc/mysql/my.cnf

然後如果我們的/var/lib/mysql目錄不爲空的話,就會報下面的錯誤

xtrabackup --copy-back --target-dir=/home/full/
encryption: using gcrypt 1.6.5
xtrabackup version 2.4.11 based on MySQL server 5.7.19 Linux (x86_64) (revision id: b4e0db5)
Original data directory /var/lib/mysql is not empty!

所以我們要刪除現有的表空間,由於我們之前是全庫備份,所以不要害怕,別忘了關閉mysql服務就好

rm -rf /var/lib/mysql/*

然後再執行恢復操作,xtrabackup就會慢慢的把文件拷貝到這個目錄下面

# xtrabackup --copy-back --target-dir=/home/full/
encryption: using gcrypt 1.6.5
xtrabackup version 2.4.11 based on MySQL server 5.7.19 Linux (x86_64) (revision id: b4e0db5)
180610 02:27:35 [01] Copying ib_logfile0 to /var/lib/mysql/ib_logfile0
180610 02:27:35 [01]        ...done
180610 02:27:35 [01] Copying ib_logfile1 to /var/lib/mysql/ib_logfile1
180610 02:27:35 [01]        ...done
180610 02:27:35 [01] Copying ibdata1 to /var/lib/mysql/ibdata1
180610 02:27:35 [01]        ...done
......
180610 02:27:54 completed OK!

然後查看一下恢復完畢之後是什麼文件

# ls -l /var/lib/mysql
total 122924
drwxr-x--- 2 root root     4096 Jun 10 02:27 dbtest
-rw-r----- 1 root root      352 Jun 10 02:27 ib_buffer_pool
-rw-r----- 1 root root 50331648 Jun 10 02:27 ib_logfile0
-rw-r----- 1 root root 50331648 Jun 10 02:27 ib_logfile1
-rw-r----- 1 root root 12582912 Jun 10 02:27 ibdata1
-rw-r----- 1 root root 12582912 Jun 10 02:27 ibtmp1
drwxr-x--- 2 root root     4096 Jun 10 02:27 mysql
drwxr-x--- 2 root root     4096 Jun 10 02:27 performance_schema
drwxr-x--- 2 root root    12288 Jun 10 02:27 sys
-rw-r----- 1 root root       29 Jun 10 02:27 xtrabackup_binlog_pos_innodb
-rw-r----- 1 root root       39 Jun 10 02:27 xtrabackup_galera_info
-rw-r----- 1 root root      455 Jun 10 02:27 xtrabackup_info
-rw-r----- 1 root root        1 Jun 10 02:27 xtrabackup_master_key_id

在看一下源數據庫裏的文件

# ls -l /var/lib/mysql
total 257932
-rw-r----- 1 mysql mysql      1941 Jun 10 01:53 9f6505094522-bin.000001
-rw-r----- 1 mysql mysql        26 Jun 10 01:29 9f6505094522-bin.index
-rw-r----- 1 mysql mysql        56 May 29 08:46 auto.cnf
-rw-r----- 1 mysql mysql       854 May 29 08:47 bf9cc24797ed-bin.000001
-rw-r----- 1 mysql mysql       823 May 29 09:18 bf9cc24797ed-bin.000002
-rw-r----- 1 mysql mysql      2602 May 29 09:44 bf9cc24797ed-bin.000003
-rw-r----- 1 mysql mysql        78 May 29 09:19 bf9cc24797ed-bin.index
-rw------- 1 mysql mysql      1676 May 29 08:46 ca-key.pem
-rw-r--r-- 1 mysql mysql      1120 May 29 08:46 ca.pem
-rw-r--r-- 1 mysql mysql      1120 May 29 08:46 client-cert.pem
-rw------- 1 mysql mysql      1680 May 29 08:46 client-key.pem
drwxr-x--- 2 mysql mysql      4096 Jun 10 01:31 dbtest
-rw-r----- 1 mysql mysql 134219048 Jun 10 01:53 galera.cache
-rw-r----- 1 mysql mysql       113 Jun 10 01:53 grastate.dat
-rw-r----- 1 mysql mysql       170 Jun 10 01:29 gvwstate.dat
-rw-r----- 1 mysql mysql       352 May 29 09:44 ib_buffer_pool
-rw-r----- 1 mysql mysql  50331648 Jun 10 02:03 ib_logfile0
-rw-r----- 1 mysql mysql  50331648 May 29 08:46 ib_logfile1
-rw-r----- 1 mysql mysql  12582912 Jun 10 02:03 ibdata1
-rw-r----- 1 mysql mysql  12582912 Jun 10 02:03 ibtmp1
-rw-r----- 1 mysql mysql     34395 May 29 09:20 innobackup.backup.log
drwxr-x--- 1 mysql mysql      4096 May 29 08:46 mysql
-rw-rw---- 1 root  root          3 Jun 10 01:29 mysqld_safe.pid
drwxr-x--- 1 mysql mysql      4096 May 29 08:46 performance_schema
-rw------- 1 mysql mysql      1680 May 29 08:46 private_key.pem
-rw-r--r-- 1 mysql mysql       452 May 29 08:46 public_key.pem
-rw-r--r-- 1 mysql mysql      1120 May 29 08:46 server-cert.pem
-rw------- 1 mysql mysql      1680 May 29 08:46 server-key.pem
drwxr-x--- 1 mysql mysql     12288 May 29 08:47 sys
-rw-r----- 1 mysql mysql   3932160 Jun 10 02:03 xb_doublewrite

我們會發現恢復出來的文件要比原來的少,但是這並不影響正常使用,很多文件在mysql啓動的時候都會新建。現在我們需要把/var/lib/mysql下面的文件的owner都從root換成mysql

$ chown -R mysql:mysql /var/lib/mysql

然後就可以啓動mysql服務器了,我這裏是開啓pxc集羣

/etc/init.d/mysql bootstrap-pxc

然後查看一下數據是否恢復成功,由於是全庫備份,所以我們root用戶密碼還是和源庫是一樣的。

mysql> select * from dbtest.table1;
+----+-------------+---------------------+
| id | name        | birthday            |
+----+-------------+---------------------+
|  1 | befor_full1 | 2018-06-10 01:31:54 |
|  2 | befor_full2 | 2018-06-10 01:32:00 |
+----+-------------+---------------------+
2 rows in set (0.02 sec)

可以看到,全庫數據恢復成功。

下面我們進行第二項,進行兩次增備,然後學習如何恢復增備的數據庫。

首先我們在源庫第一次增備前插入兩條數據,並新建一個用戶並授權,查看對於用戶表的操作能否被增備

mysql> use dbtest;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into table1 values (4,'befor_inc1_2',NOW());
Query OK, 1 row affected (0.06 sec)

mysql> insert into table1 values (3,'befor_inc1_1',NOW());
Query OK, 1 row affected (0.14 sec)

mysql> select * from table1;
+----+--------------+---------------------+
| id | name         | birthday            |
+----+--------------+---------------------+
|  1 | befor_full1  | 2018-06-10 01:31:54 |
|  2 | befor_full2  | 2018-06-10 01:32:00 |
|  3 | befor_inc1_1 | 2018-06-10 02:38:13 |
|  4 | befor_inc1_2 | 2018-06-10 02:37:55 |
+----+--------------+---------------------+
4 rows in set (0.00 sec)

再創建一個用戶

mysql> CREATE USER 'alex'@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.08 sec)

mysql> select user,host from mysql.user;
+---------------+-----------+
| user          | host      |
+---------------+-----------+
| alex          | %         |
| root          | %         |
| bkpuser       | localhost |
| mysql.session | localhost |
| mysql.sys     | localhost |
| sstuser       | localhost |
+---------------+-----------+
6 rows in set (0.00 sec)

mysql> grant create,select,update,insert,delete on dbtest.* to 'alex'@'%';
Query OK, 0 rows affected (0.08 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.08 sec)

使用該用戶登陸,是可以查看該表的

# mysql -ualex -p123456

mysql> select * from table1;
ERROR 1046 (3D000): No database selected
mysql> select * from dbtest.table1;
+----+--------------+---------------------+
| id | name         | birthday            |
+----+--------------+---------------------+
|  1 | befor_full1  | 2018-06-10 01:31:54 |
|  2 | befor_full2  | 2018-06-10 01:32:00 |
|  3 | befor_inc1_1 | 2018-06-10 02:38:13 |
|  4 | befor_inc1_2 | 2018-06-10 02:37:55 |
+----+--------------+---------------------+
4 rows in set (0.00 sec)

然後我們開始第一次增備,在這之前,我們先看一下之前全備的LSN號,LSN號是什麼東西這裏就不贅述了,只要知道只要全備和多個增備的LSN號連續,那麼就可以逐個進行恢復。可以再備份目錄xtrabackup_checkpoints文件中看到,其中全備的from_lsn=0,增備的from_lsn應該等於上一個增備或者全備的to_lsn

# cat /home/full/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 2591149
last_lsn = 2591158
compact = 0
recover_binlog_info = 1
$ xtrabackup --backup --user=bkpuser --password=123456 --target-dir=/home/inc1 --incremental-basedir=/home/full/

這裏面--target-dir是你要把本次增備的文件放到那個文件夾下,--incremental-basedir是上次全備或者增備出來的文件夾。當第一次增備的時候,一般填上次全備,第二次增備的時候,如果--incremental-basedir填上次全備,那麼本次增備就會包含上次全備到現在變化的內容,相當於oracle依次做1級,2級,3級。。。增備如果--incremental-basedir填第一次增備的目錄,那麼該次增備只包含第一次增備到現在的變化,文件會更小,相當於oracle rman裏面每次都做1級增備;。

發現會因爲權限不足而報錯

# xtrabackup --backup --user=bkpuser --password=123456 --target-dir=/home/inc1 --incremental-basedir=/home/full/
encryption: using gcrypt 1.6.5
180610 03:30:44  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/var/run/mysqld/mysqld.sock' as 'bkpuser'  (using password: YES).
180610 03:30:44  version_check Connected to MySQL server
180610 03:30:44  version_check Executing a version check against the server...
180610 03:30:44  version_check Done.
180610 03:30:44 Connecting to MySQL server host: localhost, user: bkpuser, password: set, port: 3306, socket: /var/run/mysqld/mysqld.sock
Using server version 5.7.21-20-57-log
xtrabackup version 2.4.11 based on MySQL server 5.7.19 Linux (x86_64) (revision id: b4e0db5)
incremental backup from 2591149 is enabled.
xtrabackup: uses posix_fadvise().
xtrabackup: cd to /var/lib/mysql
xtrabackup: open files limit requested 0, set to 1048576
xtrabackup: using the following InnoDB configuration:
xtrabackup:   innodb_data_home_dir = .
xtrabackup:   innodb_data_file_path = ibdata1:12M:autoextend
xtrabackup:   innodb_log_group_home_dir = ./
xtrabackup:   innodb_log_files_in_group = 2
xtrabackup:   innodb_log_file_size = 50331648
InnoDB: Number of pools: 1
180610 03:30:44 >> log scanned up to (2595766)
xtrabackup: Generating a list of tablespaces
InnoDB: Allocated tablespace ID 21 for sys/sys_config, old maximum was 0
Error: failed to execute query FLUSH NO_WRITE_TO_BINLOG CHANGED_PAGE_BITMAPS: Access denied; you need (at least one of) the SUPER privilege(s) for this operation

這是因爲我們剛纔再給bkpuser授權時,沒有授予SUPER權限,本身不影響數據的增備,但是我們剛剛建立了新用戶alex並且授權了,所以bkpuser的權限就不夠了,我們可以換用root來進行這次增備,或者給bkpuser授權super來解決。其中增備的時間也不會特別短,跟全備差不多的時間,雖然只有兩行變更。

# xtrabackup --backup --user=root --password=123456 --target-dir=/home/inc1 --incremental-basedir=/home/full/
encryption: using gcrypt 1.6.5
180610 03:36:48  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/var/run/mysqld/mysqld.sock' as 'root'  (using password: YES).
180610 03:36:48  version_check Connected to MySQL server
180610 03:36:48  version_check Executing a version check against the server...
180610 03:36:48  version_check Done.
180610 03:36:48 Connecting to MySQL server host: localhost, user: root, password: set, port: 3306, socket: /var/run/mysqld/mysqld.sock
Using server version 5.7.21-20-57-log
xtrabackup version 2.4.11 based on MySQL server 5.7.19 Linux (x86_64) (revision id: b4e0db5)
incremental backup from 2591149 is enabled.
xtrabackup: uses posix_fadvise().
xtrabackup: cd to /var/lib/mysql
xtrabackup: open files limit requested 0, set to 1048576
xtrabackup: using the following InnoDB configuration:
xtrabackup:   innodb_data_home_dir = .
xtrabackup:   innodb_data_file_path = ibdata1:12M:autoextend
xtrabackup:   innodb_log_group_home_dir = ./
xtrabackup:   innodb_log_files_in_group = 2
xtrabackup:   innodb_log_file_size = 50331648
InnoDB: Number of pools: 1
......
xtrabackup: Transaction log of lsn (2595757) to (2595782) was copied.
180610 03:37:09 completed OK

備份完成後,我們看一下增備的lsn碼是不是與上次全備連續

# cat /home/inc1/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 2591149
to_lsn = 2595773
last_lsn = 2595782
compact = 0
recover_binlog_info = 1

果然是連續的,而且backup_type上還能告訴我們這個備份是個增備


然後我們進行第四項,插入兩條數據後做第二次增備

這次我們使用alex用戶進行插入

mysql> insert into table1 values (5,'befor_inc2_1',NOW());
Query OK, 1 row affected (0.08 sec)

mysql> insert into table1 values (6,'befor_inc2_2',NOW());
Query OK, 1 row affected (0.15 sec)

mysql> select * from table1;
+----+--------------+---------------------+
| id | name         | birthday            |
+----+--------------+---------------------+
|  1 | befor_full1  | 2018-06-10 01:31:54 |
|  2 | befor_full2  | 2018-06-10 01:32:00 |
|  3 | befor_inc1_1 | 2018-06-10 02:38:13 |
|  4 | befor_inc1_2 | 2018-06-10 02:37:55 |
|  5 | befor_inc2_1 | 2018-06-10 03:40:37 |
|  6 | befor_inc2_2 | 2018-06-10 03:40:44 |
+----+--------------+---------------------+
6 rows in set (0.00 sec)

然後開始進行第二次增備,這次增備有兩個選擇,一是基於上一次全備進行增備,那麼第一次增備將會失去作用,因爲這樣就包含了上次全備到第二次增備的全部變化內容。相當於Oracle數據庫每次做1級,2級,3級備份。而第二種選擇是基於第一次增備,這樣文件會小一些,但是如果第一次增備丟失了,第二次增備也就沒法恢復了,相當於Oracle每次都做1級備份。

爲了演示基於增備的增備,所以我選用第二種方式,基於第一次的變化再變化的內容,爲了不使用root,我們把SUPER權限授予bkpuser。

mysql> GRANT SUPER ON *.* TO 'bkpuser'@'localhost';
Query OK, 0 rows affected (0.08 sec)


# xtrabackup --backup --user=bkpuser --password=123456 --target-dir=/home/inc2 --incremental-basedir=/home/inc1
encryption: using gcrypt 1.6.5
180610 03:50:01  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/var/run/mysqld/mysqld.sock' as 'bkpuser'  (using password: YES).
180610 03:50:01  version_check Connected to MySQL server
180610 03:50:01  version_check Executing a version check against the server...
180610 03:50:01  version_check Done.
180610 03:50:01 Connecting to MySQL server host: localhost, user: bkpuser, password: set, port: 3306, socket: /var/run/mysqld/mysqld.sock
Using server version 5.7.21-20-57-log
xtrabackup version 2.4.11 based on MySQL server 5.7.19 Linux (x86_64) (revision id: b4e0db5)
incremental backup from 2595773 is enabled.
xtrabackup: uses posix_fadvise().
xtrabackup: cd to /var/lib/mysql
xtrabackup: open files limit requested 0, set to 1048576
xtrabackup: using the following InnoDB configuration:
xtrabackup:   innodb_data_home_dir = .
xtrabackup:   innodb_data_file_path = ibdata1:12M:autoextend
xtrabackup:   innodb_log_group_home_dir = ./
xtrabackup:   innodb_log_files_in_group = 2
xtrabackup:   innodb_log_file_size = 50331648
......
180610 03:50:22 [00] Writing /home/inc2/xtrabackup_info
180610 03:50:22 [00]        ...done
xtrabackup: Transaction log of lsn (2600041) to (2600066) was copied.
180610 03:50:22 completed OK!

順便來看一下inc2的LSN碼是不是和第一次增備連續

# cat /home/inc2/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 2595773
to_lsn = 2600057
last_lsn = 2600066
compact = 0
recover_binlog_info = 1

然後我們還是和之前一樣,將/home/inc1,/home/inc2進行打包,和之前的全備打包一起拷貝到另外一臺服務器上。注意不是之前做實驗的那臺服務器,因爲我們要重新prepare,之前prepare過的已經不能用了。

# tar -Jcf inc1.tar.xz inc1
# tar -Jcf inc2.tar.xz inc2

我們將三個壓縮包全部解壓到新服務器上,然後我們先恢復第一次增備

這裏要注意,我們依然要做prepare,而且是做兩次prepare,第一次是把全備給prepare,不過這次和上次不一樣,這次要加入--apply-log-only參數,因爲在每個備份過程中,都會碰到一些事務進來執行,而備份結束時可能有些事務並沒有執行完畢,所以在默認prepare中這些事務就會被回滾(rollback),而加入了--apply-log-only就不會回滾這些事務,而是等待prepare下次增備。第二次prepare就是準備第一次增備的目錄,這個prepare目的就是把第一次增備期間發生的變化寫入到全備的目錄中去,然後第一次增備的目錄就沒有用處了,因爲我們最終拷貝表空間文件是把增備目錄拷貝過去。無論多少個增備,最後prepare的那個增備是不能加--apply-log-only參數的,因爲最後一次增備還沒有完成的事務就要徹底回滾來保證一致性。

首先prepare全備

$ xtrabackup --prepare --apply-log-only --target-dir=/home/full

然後prepare第一次增備

$ xtrabackup --prepare --target-dir=/home/full --incremental-dir=/home/inc1

這裏的--target-dir是上一次全備的目錄,因爲我們要將第一次增備期間的變化寫入到全備目錄裏,再拷貝到表空間中,所以我們--incremental-dir填第一次增備的目錄,--target-dir填全備的目錄。由於這次不考慮第二次增備,所以第一次增備就是最後一次增備,所以去掉--apply-log-only,回滾未提交的事務。

然後停止數據庫,刪除表空間文件,開始複製,注意在複製的時候--target-dir填全備的路徑,不要填增備的,因爲在prepare完成之後,增備的就可以刪掉了

/etc/init.d/mysql stop
rm -rf /var/lib/mysql/*
xtrabackup --copy-back --target-dir=/home/full

然後我們登陸數據庫觀察,兩行數據是否恢復成功,看看user表中的用戶是否創建成功,權限是否正常

# chown -R mysql:mysql /var/lib/mysql
# /etc/init.d/mysql bootstrap-pxc
 * Bootstrapping Percona XtraDB Cluster database server mysqld                                [ OK ]

# mysql -ualex -p
Enter password:

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from dbtest.table1;
+----+--------------+---------------------+
| id | name         | birthday            |
+----+--------------+---------------------+
|  1 | befor_full1  | 2018-06-10 01:31:54 |
|  2 | befor_full2  | 2018-06-10 01:32:00 |
|  3 | befor_inc1_1 | 2018-06-10 02:38:13 |
|  4 | befor_inc1_2 | 2018-06-10 02:37:55 |
+----+--------------+---------------------+
4 rows in set (0.01 sec)

可以看到,alex用戶可以正常使用,兩條增量數據也恢復成功。

下面進行第六項,根據全備,第一次增備,第二次增備來恢復數據庫。

整個步驟和上面恢復一次增備差不多,唯一的差別就在於--apply-log-only只寫在第二次增備的prepare上。

首先我們找一個新服務器,或者把之前tar包解壓出來的目錄都刪掉,因爲我們要重新prepare

# /etc/init.d/mysql stop
 * Stopping MySQL (Percona XtraDB Cluster) mysqld                                                                [ OK ]
root@a0f24357ff78:/home# rm -rf /home/full/
root@a0f24357ff78:/home# rm -rf /home/inc1/
root@a0f24357ff78:/home# rm -rf /home/inc2/
root@a0f24357ff78:/home# tar -Jxf /home/full.tar.xz
root@a0f24357ff78:/home# tar -Jxf /home/inc1.tar.xz
root@a0f24357ff78:/home# tar -Jxf /home/inc2.tar.xz
然後步驟類似,也是先prepare,一定記住--apply-log-only只有最後一個增備不寫

$ xtrabackup --prepare --apply-log-only --target-dir=/home/full
$ xtrabackup --prepare --apply-log-only --target-dir=/home/full --incremental-dir=/home/inc1
$ xtrabackup --prepare --target-dir=/home/full --incremental-dir=/home/inc2

然後拷貝並重啓數據庫

#/etc/init.d/mysql stop
# rm -rf /var/lib/mysql/*
# xtrabackup --copy-back --target-dir=/home/full
# chown -R mysql:mysql /var/lib/mysql
# /etc/init.d/mysql bootstrap-pxc
 * Bootstrapping Percona XtraDB Cluster database server mysqld                                [ OK ]

使用alex用戶登陸進去看看是不是完整的6條數據

mysql> select * from dbtest.table1;
+----+--------------+---------------------+
| id | name         | birthday            |
+----+--------------+---------------------+
|  1 | befor_full1  | 2018-06-10 01:31:54 |
|  2 | befor_full2  | 2018-06-10 01:32:00 |
|  3 | befor_inc1_1 | 2018-06-10 02:38:13 |
|  4 | befor_inc1_2 | 2018-06-10 02:37:55 |
|  5 | befor_inc2_1 | 2018-06-10 03:40:37 |
|  6 | befor_inc2_2 | 2018-06-10 03:40:44 |
+----+--------------+---------------------+
6 rows in set (0.01 sec)
可以看到新用戶alex的權限和table1中的數據都完整恢復了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章