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


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 

安裝之后,innobackupexxtrabackupxbstream, 和 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 "${innobackupex_args[@]}" "${todays_dir}" > "${todays_dir}/${backup_type}-${now}.xbstream.incomplete" 2> "${log_file}" mv "${todays_dir}/${backup_type}-${now}.xbstream.incomplete" "${todays_dir}/${backup_type}-${now}.xbstream" } sanity_check && set_options && rotate_old && take_backup # Check success and print message if tail -1 "${log_file}" | grep -q "completed OK"; then printf "Backup successful!\n" printf "Backup created at %s/%s-%s.xbstream\n" "${todays_dir}" "${backup_type}" "${now}" else error "Backup failure! Check ${log_file} for more information" fi 

這個腳本完成了如下功能:

  • 每天第一次運行時創建一個加密的壓縮的全備份
  • 第二次執行時,會創建加密的壓縮的增量備份
  • 維護全備份的歷史默認保留 3 天的全備份和增量備份,如需修改天數,請自行修改本腳本。

當這個腳本執行,一個日期的文件夾會被創建,如果是第一次備份,文件名以 full- 開頭,表示全備份,從第二次開始,文件名以 incremental- 開頭,表示增量備份,文件名后面代表備份時的系統時間。

腳本執行后,會生成一個文件名為 backup-progress.log 的日志文件,如有問題,可以查看。還有一個 xtrabackup_checkpoints 文件,用於存儲備份時的元數據,這個文件不能刪除,因為下一次創建增量備份時需要用到這里的參數。

創建完成后,保存這個文件,並更改這個腳本為可執行

$ sudo chmod +x /usr/local/bin/backup-mysql.sh 

創建 extract-mysql.sh 腳本

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

腳本內容如下:

#!/bin/bash export LC_ALL=C backup_owner="backup" encryption_key_file="/backups/mysql/encryption_key" log_file="extract-progress.log" number_of_args="${#}" 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. Try checking the \"${log_file}\" file for more information."' 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 qpress binary is installed if ! command -v qpress >/dev/null 2>&1; then error "Could not find the \"qpress\" command. Please install it and try again." fi # Check whether any arguments were passed if [ "${number_of_args}" -lt 1 ]; then error "Script requires at least one \".xbstream\" file as an argument." 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 } do_extraction () { for file in "${@}"; do base_filename="$(basename "${file%.xbstream}")" restore_dir="./restore/${base_filename}" printf "\n\nExtracting file %s\n\n" "${file}" # Extract the directory structure from the backup file mkdir --verbose -p "${restore_dir}" xbstream -x -C "${restore_dir}" < "${file}" innobackupex_args=( "--parallel=${processors}" "--decrypt=AES256" "--encrypt-key-file=${encryption_key_file}" "--decompress" ) innobackupex "${innobackupex_args[@]}" "${restore_dir}" find "${restore_dir}" -name "*.xbcrypt" -exec rm {} \; find "${restore_dir}" -name "*.qp" -exec rm {} \; printf "\n\nFinished work on %s\n\n" "${file}" done > "${log_file}" 2>&1 } sanity_check && do_extraction "$@" ok_count="$(grep -c 'completed OK' "${log_file}")" # Check the number of reported completions. For each file, there is an # informational "completed OK". If the processing was successful, an # additional "completed OK" is printed. Together, this means there should be 2 # notices per backup file if the process was successful. if (( $ok_count != 2 * $# )); then error "It looks like something went wrong. Please check the \"${log_file}\" file for additional information" else printf "Extraction complete! Backup directories have been extracted to the \"restore\" directory.\n" fi 

這個腳本與 backup-mysql.sh 不能,這個腳本在希望恢復備份時使用。會提取(解壓並解密)以 xbstream 為后綴的文件。

這個腳本執行之后,會把提取后的文件放到 restore 文件夾下,包含當天的全備份文件和增量備份的文件。您可以自己分析,恢復到哪個時點。

創建完成后,保存這個文件,並更改這個腳本為可執行

$ sudo chmod +x /usr/local/bin/extract-mysql.sh 

創建 prepare-mysql.sh 腳本

最后我們創建 prepare-mysql.sh,將確認后的增量備份合並到全量備份中,這樣就生成了那個時點的數據庫快照。

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

腳本內容如下:

#!/bin/bash export LC_ALL=C shopt -s nullglob incremental_dirs=( ./incremental-*/ ) full_dirs=( ./full-*/ ) shopt -u nullglob backup_owner="backup" log_file="prepare-progress.log" full_backup_dir="${full_dirs[0]}" # 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. Try checking the \"${log_file}\" file for more information."' 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 a single full backup directory are available if (( ${#full_dirs[@]} != 1 )); then error "Exactly one full backup directory is required." fi } do_backup () { # Apply the logs to each of the backups printf "Initial prep of full backup %s\n" "${full_backup_dir}" innobackupex --redo-only --apply-log "${full_backup_dir}" for increment in "${incremental_dirs[@]}"; do printf "Applying incremental backup %s to %s\n" "${increment}" "${full_backup_dir}" innobackupex --redo-only --apply-log --incremental-dir="${increment}" "${full_backup_dir}" done printf "Applying final logs to full backup %s\n" "${full_backup_dir}" innobackupex --apply-log "${full_backup_dir}" } sanity_check && do_backup > "${log_file}" 2>&1 # Check the number of reported completions. Each time a backup is processed, # an informational "completed OK" and a real version is printed. At the end of # the process, a final full apply is performed, generating another 2 messages. ok_count="$(grep -c 'completed OK' "${log_file}")" if (( ${ok_count} == 2 * (${#full_dirs[@]} + ${#incremental_dirs[@]} + 1) )); then cat << EOF Backup looks to be fully prepared. Please check the "prepare-progress.log" file to verify before continuing. If everything looks correct, you can apply the restored files. First, stop MySQL and move or remove the contents of the MySQL data directory: sudo systemctl stop mysql sudo mv /var/lib/mysql/ /tmp/ Then, recreate the data directory and copy the backup files: sudo mkdir /var/lib/mysql sudo innobackupex --copy-back ${PWD}/$(basename "${full_backup_dir}") Afterward the files are copied, adjust the permissions and restart the service: sudo chown -R mysql:mysql /var/lib/mysql sudo find /var/lib/mysql -type d -exec chmod 750 {} \\; sudo systemctl start mysql EOF else error "It looks like something went wrong. Check the \"${log_file}\" file for more information." fi 

這個腳本將在本目錄查找以 full- 或 incremental- 為前綴的目錄,使用 MySQL 的日志應用提交的事務到全量備份,之后再將增量備份的事務提交到全量備份中。

如果所有的備份都被結合,那么未被提交的事務將會回滾,這時,這個 full- 開頭的全量備份文件夾,里面的數據,就是當時 MySQL 的數據文件。

創建完成后,保存這個文件,並更改這個腳本為可執行

$ sudo chmod +x /usr/local/bin/prepare-mysql.sh 

測試這個 MySQL 的備份和恢復腳本

創建一個全備份

使用 backup 用戶執行 backup-mysql.sh

$ sudo -u backup /usr/local/bin/backup-mysql.sh Backup successful! Backup created at /backups/mysql/Wed/full-05-10-2017_17-16-44.xbstream 

如果一切順利,輸出會看到 Backup successful!,這樣創建了一個當天的文件夾(本例為 Wed),並且創建了一個以 full- 開頭的全量備份。

讓我們進入這個目錄看一下

$ cd /backups/mysql/"$(date +%a)" $ ls backup-progress.log full-05-10-2017_17-16-44.xbstream xtrabackup_checkpoints 

如上 backup-progress.log,為日志文件,我們看一下他的內容

$ tail backup-progress.log 170510 17:16:46 All tables unlocked 170510 17:16:46 [00] Compressing, encrypting and streaming ib_buffer_pool to <STDOUT> 170510 17:16:46 [00] ...done 170510 17:16:46 Backup created in directory '/backups/mysql/Wed/' 170510 17:16:46 [00] Compressing, encrypting and streaming backup-my.cnf 170510 17:16:46 [00] ...done 170510 17:16:46 [00] Compressing, encrypting and streaming xtrabackup_info 170510 17:16:46 [00] ...done xtrabackup: Transaction log of lsn (2541849) to (2541858) was copied. 170510 17:16:46 completed OK! 

看到 completed OK!,表示備份沒有問題。

在看一下 xtrabackup_checkpoints 的內容

$ cat xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 2541849 last_lsn = 2541858 compact = 0 recover_binlog_info = 0 

這個例子表示,全備份是將日志序列號 log sequence number (LSN) 從起始點(from_lsn) 0 到終止點(to_lsn) 2541849 的備份。 last_lsn 表示當執行備份操作到的日志序列號。

創建一個增量備份

全備份創建之后,下一次創建的是增量備份,它依賴這個全備份,再一次創建增量備份時依賴的就是上次的增量備份了,這是一種鏈式依賴。

本例添加一些數據到數據庫,這樣更好感受效果。

$ sudo mysql -u root -p -e 'INSERT INTO playground.equipment (type, quant, color) VALUES ("swing", 10, "yellow");'

再次執行 backup-mysql.sh,就會創建增量備份。

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

我們查看一下

$ cd /backups/mysql/"$(date +%a)" $ ls backup-progress.log full-05-10-2017_17-16-44.xbstream incremental-05-10-2017_18-39-39.xbstream xtrabackup_checkpoints 

此時查看一下 xtrabackup_checkpoints

$ cat xtrabackup_checkpoints backup_type = incremental from_lsn = 2541849 to_lsn = 2542208 last_lsn = 2542217 compact = 0 recover_binlog_info = 0 

此時 from_lsn 已經是上次(本例為第一次備份)的 to_lsn 了,from_lsn 是 0 的時候,表示是全備份,不為 0 就是增量備份了。

提取備份

接下來,我們要提取備份文件到本分文件夾。

$ sudo -u backup /usr/local/bin/extract-mysql.sh *.xbstream Extraction complete! Backup directories have been extracted to the "restore" directory. 

看到 Extraction complete! 表示提取完畢。
這個腳本會生成一個 restore 目錄 和 extract-progress.log 日志文件。

查看一下 extract-progress.log

$ tail extract-progress.log 170510 18:47:02 [01] decrypting and decompressing ./xtrabackup_logfile.qp.xbcrypt 170510 18:47:02 [01] decrypting ./xtrabackup_checkpoints.xbcrypt 170510 18:47:02 [01] decrypting and decompressing ./ib_buffer_pool.qp.xbcrypt 170510 18:47:02 [01] decrypting and decompressing ./backup-my.cnf.qp.xbcrypt 170510 18:47:02 [01] decrypting and decompressing ./xtrabackup_info.qp.xbcrypt 170510 18:47:02 completed OK! Finished work on incremental-05-10-2017_18-39-39.xbstream 

我們進入 restore 目錄,備份文件已經准備就緒。

$ cd restore
$ ls -F
full-05-10-2017_17-16-44/  incremental-05-10-2017_18-39-39/

這是備份文件,但是還不是 MySQL 的數據文件。為達到最后的目的,我們開始准備文件。

准備文件

接下來,我們將合並這些文件。

  • 我們必須在 restore 文件夾下執行這個腳本
  • 這個文件夾下包含 full- 和 incremental- 的備份文件夾,如果我們不想恢復某些增量備份,請刪除這些 incremental- 文件夾。

恢復命令如下(注意 要在 restore 目錄下執行這個命令)

$ sudo -u backup /usr/local/bin/prepare-mysql.sh Backup looks to be fully prepared. Please check the "prepare-progress.log" file to verify before continuing. If everything looks correct, you can apply the restored files. First, stop MySQL and move or remove the contents of the MySQL data directory: sudo systemctl stop mysql sudo mv /var/lib/mysql/ /tmp/ Then, recreate the data directory and copy the backup files: sudo mkdir /var/lib/mysql sudo innobackupex --copy-back /backups/mysql/Wed/restore/full-05-10-2017_17-16-44 Afterward the files are copied, adjust the permissions and restart the service: sudo chown -R mysql:mysql /var/lib/mysql sudo find /var/lib/mysql -type d -exec chmod 750 {} \; sudo systemctl start mysql 

這表示准備完成了,腳本會輸出一些接下來恢復數據庫的步驟

還原備份數據到 MySQL 數據目錄

首先,停止 MySQL 服務

$ sudo systemctl stop mysqld 

因為備份目錄與 MySQL 的數據目錄可能有沖突,我們需要刪除或剪切 /var/lib/mysql 目錄

$ sudo mv /var/lib/mysql/ /tmp 

重新創建 /var/lib/mysql 目錄,之后賦予正確的權限

$ sudo mkdir /var/lib/mysql 

現在,我們要使用 innobackupex 將備份文件拷貝到 MySQL 的數據目錄

$ sudo innobackupex --copy-back /backups/mysql/Wed/restore/full-05-10-2017_17-16-44/ 170510 19:04:22 innobackupex: Starting the copy-back operation IMPORTANT: Please check that the copy-back run completes successfully. At the end of a successful copy-back run innobackupex prints "completed OK!". innobackupex version 2.4.7 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 6f7a799) ...... ...... 170510 19:04:33 completed OK! 

執行之后,completed OK! 說明拷貝完成,一旦文件已經就位,我們需要將修復所有者和權限,這樣 MySQL 的用戶和組就可以訪問了。

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

因為 CentOS 7 默認啟用了 SELinux,這也需要進行授權,可以先查看一下

$ ls -lh -Zd /var/lib/mysql drwxr-x--x. mysql mysql unconfined_u:object_r:var_lib_t:s0 /var/lib/mysql 

授權命令如下

$ sudo chcon -R -t mysqld_db_t /var/lib/mysql 

此時,權限已經恢復完全。

啟動 MySQL 服務,完成數據恢復。

$ sudo systemctl start mysqld 

如果數據庫啟動順利,接下來,我們查詢一下數據庫,驗證一下數據是否恢復

$ sudo mysql -u root -p -e 'SELECT * FROM playground.equipment;' Enter password: +----+-------+-------+--------+ | id | type | quant | color | +----+-------+-------+--------+ | 1 | slide | 2 | blue | | 2 | swing | 10 | yellow | +----+-------+-------+--------+ 

由此可以看到,數據順利恢復了。

數據恢復完成之后,還要注意一個非常重要的事情,我們需要刪除 restore 目錄,因為新的增量備份,不能使用本次的結果文件,而且沒有加密的備份文件,保存在磁盤也不安全。

$ cd ~ $ sudo rm -rf /backups/mysql/"$(date +%a)"/restore 

下一次恢復,我們需要重新執行 extract-mysql.sh 腳本,生成 restore 目錄,並執行 prepare-mysql.sh 准備數據。

創建 Cron 作業每小時增量備份

我們手工執行的 backup-mysql.sh 可以創建作業,定時(每小時)執行。

$ sudo vi /etc/cron.hourly/backup-mysql 

輸入如下內容

#!/bin/bash sudo -u backup systemd-cat --identifier=backup-mysql /usr/local/bin/backup-mysql.sh 

保存並關閉 :wq,讓這個腳本可以執行

$ sudo chmod +x /etc/cron.hourly/backup-mysql 

這個腳本將每小時執行一次,並且自動清除 3 天以前的備份。

我們可以手動測試一下 cron 腳本

$ sudo /etc/cron.hourly/backup-mysql 

執行完之后,我們可以使用 journal 命令查看一下日志

$ sudo journalctl -t backup-mysql -- Logs begin at Wed 2017-05-10 18:28:55 CST, end at Wed 2017-05-10 19:27:58 CST. -- May 10 19:27:13 bogon backup-mysql[6704]: Backup successful! May 10 19:27:13 bogon backup-mysql[6704]: Backup created at /backups/mysql/Wed/incremental-05-10-2017_19-27-11.xbstream 

結束語

本例使用了 xtrabackup 工具,進行了 MySQL 的熱備份和恢復

  • 全備份和增量備份
  • 提取備份文件
  • 恢復數據

參考資料

Installing Percona XtraBackup on Red Hat Enterprise Linux and CentOS
How To Configure MySQL Backups with Percona XtraBackup on Ubuntu 16.04
How To Create Hot Backups of MySQL Databases with Percona XtraBackup on CentOS 7


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM