天天看點

(轉)CentOS 7 下 MySQL 5.7 配置 Percona Xtrabackup

前言

CentOS 7 下 MySQL 5.7 配置 Percona Xtrabackup ,記錄一下大緻的安裝和配置過程。

Percona XtraBackup 的備份工具支援熱備份(即不必停止 MySQL 服務而進行備份)。熱備份方式主要是通過檔案系統級别的檔案拷貝,當需要執行崩潰恢複時,可以實作資料集内的一緻性。

參考 ​​How To Configure MySQL Backups with Percona XtraBackup on Ubuntu 16.04​​

參考文檔使用的作業系統為 Ubuntu 16.04,本例将作業系統改為 CentOS 7,指令基本一緻,主要示例一下資料庫的全備份,增量備份以及資料恢複。

環境說明

CentOS 7(Minimal Install)

$ cat /etc/redhat-release 
CentOS Linux release 7.3.1611 (Core)
      

MySQL 5.7

$ mysql --version
mysql  Ver 14.14 Distrib 5.7.18, for Linux (x86_64) using  EditLine wrapper
      

本系統初始有兩個使用者

超級管理者: root

管理組使用者: admin

安裝 Percona Xtrabackup 工具

參考 ​​Installing Percona XtraBackup on Red Hat Enterprise Linux and CentOS​​

安裝 yum 源

$ sudo yum install http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
      

查詢一下安裝包

$ sudo yum list | grep xtrabackup
percona-xtrabackup.x86_64                  2.3.8-1.el7                 percona-release-x86_64
percona-xtrabackup-22.x86_64               2.2.13-1.el7                percona-release-x86_64
percona-xtrabackup-22-debuginfo.x86_64     2.2.13-1.el7                percona-release-x86_64
percona-xtrabackup-24.x86_64               2.4.7-1.el7                 percona-release-x86_64
percona-xtrabackup-24-debuginfo.x86_64     2.4.7-1.el7                 percona-release-x86_64
percona-xtrabackup-debuginfo.x86_64        2.3.8-1.el7                 percona-release-x86_64
percona-xtrabackup-test.x86_64             2.3.8-1.el7                 percona-release-x86_64
percona-xtrabackup-test-22.x86_64          2.2.13-1.el7                percona-release-x86_64
percona-xtrabackup-test-24.x86_64          2.4.7-1.el7                 percona-release-x86_64
      

安裝 ​

​Xtrabackup​

​ 和 ​

​qpress​

​ 壓縮工具。

$ sudo yum update
$ sudo yum install percona-xtrabackup-24 qpress
      

安裝之後,​

​innobackupex​

​, ​

​xtrabackup​

​xbstream​

​, 和 ​

​qpress​

​ 指令将可以使用,本例的腳本會使用這些指令進行資料的備份和恢複。

配置一個 MySQL 備份使用者并且添加測試資料

首先使用 MySQL 的 ​

​root​

​ 使用者登入。

$ mysql -u root -p
      

建立一個 MySQL 使用者并且授權

在 MySQL 中建立一個使用者名為 ​

​backup​

​ 的使用者,并且配置設定備份的相關權限給它。

mysql> CREATE USER 'backup'@'localhost' IDENTIFIED BY 'password';
      

授予備份的相關權限

mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT, CREATE TABLESPACE, PROCESS, SUPER, CREATE, INSERT, SELECT ON *.* TO 'backup'@'localhost';
mysql> FLUSH PRIVILEGES;
      

建立測試資料,建立一個 playground 的資料庫,建立一個 equipment 的表,并且添加一條記錄到這個表裡。

mysql> CREATE DATABASE playground;
mysql> CREATE TABLE playground.equipment ( id INT NOT NULL AUTO_INCREMENT, type VARCHAR(50), quant INT, color VARCHAR(25), PRIMARY KEY(id));
mysql> INSERT INTO playground.equipment (type, quant, color) VALUES ("slide", 2, "blue");
      

此後我們将用這個資料庫檢視測試備份和恢複的效果。

mysql> SELECT * FROM playground.equipment;
+----+-------+-------+-------+
| id | type  | quant | color |
+----+-------+-------+-------+
|  1 | slide |     2 | blue  |
+----+-------+-------+-------+
1 row in set (0.00 sec)
      

在我們退出 MySQL 會話前,我們先檢查一下 ​

​datadir​

​ 變量。因為我們還要建立一個作業系統的 ​

​backup​

​ 使用者,而且這個需要有權限通路這個目錄。

mysql> SELECT @@datadir;
+-----------------+
| @@datadir       |
+-----------------+
| /var/lib/mysql/ |
+-----------------+
1 row in set (0.00 sec)
      

記住這個目錄,現在可以退出 MySQL 了。

mysql> exit
Bye
      

配置作業系統的備份使用者并授權

建立 backup 使用者,不需要登入系統,沒有 home 目錄

$ sudo useradd -M -s /sbin/nologin backup
      

确認一下 backup 使用者群組

$ grep backup /etc/passwd /etc/group
/etc/passwd:backup:x:1001:1001::/home/backup:/sbin/nologin
/etc/group:backup:x:1001:
      

MySQL 的資料目錄 ​

​/var/lib/mysql​

​ 的所有者和所有組是 ​

​mysql​

​。

  1. 我們需要将 backup 加入到 mysql 組裡,這樣 backup 就可以通路 mysql 組的目錄和檔案。
  2. 我們需要将 ​

    ​sudo​

    ​ 加入到 backup 組裡,這樣我們就可以通路 backup 使用者群組權限的目錄和檔案。

指令執行如下

$ sudo usermod -aG mysql backup
$ sudo usermod -aG backup ${USER}
      

此時我們再檢查一下 backup 的組

$ grep backup /etc/group
mysql:x:27:backup
backup:x:1001:admin
      

新加入的組不會立即生效,需要執行如下指令

$ exec su - ${USER}
      

執行之後,可以使用如下指令确認

$ id -nG
admin wheel backup
      
注意: ​

​admin​

​ 是 admin 的組,​

​wheel​

​ 是 CentOS 預設的 sudo 組,​

​backup​

​ 是新增的 mysql 備份的組。

建立備份相關的資源

現在我們已經有了 Mysql 使用者 ​

​backup​

​, 系統使用者 ​

​backup​

​,我們需要建立配置檔案,密鑰檔案和其他腳本,這樣我們就可以建立并保護備份的安全。

建立 MySQL 備份的配置檔案

我們将 MySQL 備份使用者 ​

​backup​

​ 的使用者名和密碼放到配置中。

$ sudo mkdir /etc/mysql
$ sudo vi /etc/mysql/backup.cnf
      

加入如下内容:

[client]
user=backup
password=password 
      

儲存并退出 ​

​:wq​

​,這樣 MySQL 的配置檔案就建立完畢,以後備份使用者就會使用這個檔案的配置登入 MySQL ,注意 ​

​password=password​

​ 這個密碼是 MySQL 裡面的使用者 ​

​backup​

​ 的密碼。

建立備份的根目錄

本例使用 ​

​/backups/mysql​

​ 為備份檔案的根目錄,使用如下指令建立:

$ sudo mkdir -p /backups/mysql
      

對這個目錄的所有者和所有組進行配置設定, 所有者為 backup,所有組為 mysql

$ sudo chown backup:mysql /backups/mysql
      

這樣 backup 使用者就可以進入并操作這個目錄了

建立密鑰保護備份檔案安全

因為資料庫檔案是非常重要的檔案,是以安全非常重要。 ​

​innobackupex​

​ 工具提供了加密和解密的功能。為此,我們隻需要提供一個密鑰即可。

我們使用 ​

​openssl​

​ 指令來建立一個密鑰

$ printf '%s' "$(openssl rand -base64 24)" | sudo tee /backups/mysql/encryption_key && echo
      

修改這個檔案的權限,保證這個檔案隻能 ​

​backup​

​ 使用者可以使用。

$ sudo chown backup:backup /backups/mysql/encryption_key
$ sudo chmod 600 /backups/mysql/encryption_key
      

建立備份和恢複的腳本

目前安全方面的準備已經完成,我們需要建立 3 個腳本,來執行備份(加密備份),釋放(解密)和恢複準備的工作。

  • ​backup-mysql.sh​

    ​: 這個腳本完成備份資料庫,對備份的檔案進行加密和壓縮,他會根據日期建立全量和增量的備份,預設儲存 3 天的備份。
  • ​extract-mysql.sh​

    ​: 這個腳本會解壓并解密備份檔案,并将檔案放到指定的檔案夾中。
  • ​prepare-mysql.sh​

    ​: 這個腳本為恢複做最後的準備,将增量檔案合并到全備份中。并且記錄執行的日志,如果這個腳本執行完,那麼剩下的就是将恢複的資料庫替換即可。

建立 backup-mysql.sh 腳本

$ sudo vi /usr/local/bin/backup-mysql.sh
      

腳本内容如下:

#!/bin/bash
    
export LC_ALL=C
    
days_of_backups=3  # Must be less than 7
backup_owner="backup"
parent_dir="/backups/mysql"
defaults_file="/etc/mysql/backup.cnf"
todays_dir="${parent_dir}/$(date +%a)"
log_file="${todays_dir}/backup-progress.log"
encryption_key_file="${parent_dir}/encryption_key"
now="$(date +%m-%d-%Y_%H-%M-%S)"
processors="$(nproc --all)"
    
# Use this to echo to standard error
error () {
    printf "%s: %s\n" "$(basename "${BASH_SOURCE}")" "${1}" >&2
    exit 1
}
    
trap 'error "An unexpected error occurred."' ERR
    
sanity_check () {
    # Check user running the script
    if [ "$USER" != "$backup_owner" ]; then
        error "Script can only be run as the \"$backup_owner\" user"
    fi
    
    # Check whether the encryption key file is available
    if [ ! -r "${encryption_key_file}" ]; then
        error "Cannot read encryption key at ${encryption_key_file}"
    fi
}
    
set_options () {
    # List the innobackupex arguments
    #declare -ga innobackupex_args=(
    innobackupex_args=(
        "--defaults-file=${defaults_file}"
        "--extra-lsndir=${todays_dir}"
        "--compress"
        "--stream=xbstream"
        "--encrypt=AES256"
        "--encrypt-key-file=${encryption_key_file}"
        "--parallel=${processors}"
        "--compress-threads=${processors}"
        "--encrypt-threads=${processors}"
        "--slave-info"
        "--incremental"
    )
    
    backup_type="full"
    
    # Add option to read LSN (log sequence number) if a full backup has been
    # taken today.
    if grep -q -s "to_lsn" "${todays_dir}/xtrabackup_checkpoints"; then
        backup_type="incremental"
        lsn=$(awk '/to_lsn/ {print $3;}' "${todays_dir}/xtrabackup_checkpoints")
        innobackupex_args+=( "--incremental-lsn=${lsn}" )
    fi
}
    
rotate_old () {
    # Remove the oldest backup in rotation
    day_dir_to_remove="${parent_dir}/$(date --date="${days_of_backups} days ago" +%a)"
    
    if [ -d "${day_dir_to_remove}" ]; then
        rm -rf "${day_dir_to_remove}"
    fi
}
    
take_backup () {
    # Make sure today's backup directory is available and take the actual backup
    mkdir -p "${todays_dir}"
    find "${todays_dir}" -type f -name "*.incomplete" -delete
    innobackupex "${