前書き

多くの場合、データベースにはインフラストラクチャの最も価値のある情報の一部が格納されます。 このため、事故やハードウェア障害が発生した場合のデータ損失を防ぐために、信頼できるバックアップを作成することが重要です。

Percona XtraBackupバックアップツールは、システムの実行中にMySQLデータの「ホット」バックアップを実行する方法を提供します。 これを行うには、ファイルシステムレベルでデータファイルをコピーし、クラッシュリカバリを実行してデータセット内の一貫性を実現します。

このガイドでは、Ubuntu 16.04サーバー上のMySQLデータのバックアップを自動化するシステムを作成します。 スクリプトのグループでcronおよびPerconaツールを使用して、問題が発生した場合のリカバリに使用できる定期的で安全なバックアップを作成します。

前提条件

このガイドを完了するには、管理タスク用に設定された非ルート `+ sudo +`ユーザーを持つUbuntu 16.04サーバーが必要です。 「Ubuntu16.04での初期サーバー設定」ガイドに従って、これらの権限を持つユーザーを設定できます。サーバー上。

`+ sudo +`ユーザーが利用可能になったら、MySQLをインストールする必要があります。 使用するパッケージに応じて、これらのガイドのいずれかを使用できます。 最初のガイドはUbuntuの公式リポジトリを使用したい場合に適していますが、2番目のガイドは最新の機能が必要な場合に適しています。

MySQLをインストールしたら、 `+ sudo +`ユーザーとしてサーバーにログインして続行します。

Percona Xtrabackupツールのインストール

最初に行う必要があるのは、実際のP​​erconaバックアップユーティリティをインストールすることです。 このプロジェクトは、MySQLサーバーに追加してパッケージにアクセスできる独自のリポジトリを保持しています。

開始するには、https://www.percona.com/downloads/percona-release/ubuntu/latest/ [UbuntuのPerconaリリースページ]にアクセスして、リポジトリをインストールするための最新の `+ .deb +`パッケージを見つけます。 「Xenial Xerus」というコードネームのUbuntu 16.04を使用しているため、「xenial」パッケージを選択する必要があります。 対応するリンクを右クリックして、アドレスをコピーします。

リンクをコピーしたら、 `+ / tmp `ディレクトリに移動し、 ` curl +`でリポジトリ設定パッケージをダウンロードします。

cd /tmp
curl -LO https://repo.percona.com/apt/.deb

次に、 `+ dpkg `を使用してダウンロードしたパッケージをインストールします。これにより、システム上のPercona ` apt +`リポジトリが設定されます。

sudo dpkg -i percona*

新しいリポジトリを設定したら、ローカルパッケージインデックスを更新して、新しく利用可能なパッケージに関する情報を取得します。 次に、リポジトリからXtraBackupツールと `+ qpress +`圧縮ユーティリティをインストールします。

sudo apt-get update
sudo apt-get install percona-xtrabackup-24 qpress

他のバンドルされたユーティリティの中で、 + xtrabackup ++ xbstream +、および `+ qpress +`コマンドが利用可能になります。 スクリプトはこれらのそれぞれを使用してバックアップを実行し、データを復元します。

MySQLバックアップユーザーの構成とテストデータの追加

開始するには、MySQLルートユーザーとの対話型MySQLセッションを開始します。

mysql -u root -p

MySQLのインストール中に選択した管理パスワードの入力を求められます。 パスワードを入力すると、MySQLセッションにドロップされます。

適切な特権を持つMySQLユーザーを作成する

最初に行う必要があるのは、バックアップタスクを処理するように構成された新しいMySQLユーザーを作成することです。 システムの実行中にデータを安全にコピーするために必要な権限のみをこのユーザーに付与します。

アカウントの目的を明確にするために、新しいユーザーを「+ backup +」と呼びます。 ユーザーの資格情報を安全なファイルに配置するため、複雑なパスワードを自由に選択してください。

CREATE USER 'backup'@'localhost' IDENTIFIED BY '';

次に、新しい `+ backup +`ユーザーに、データベースシステムですべてのバックアップアクションを実行するために必要な権限を付与する必要があります。 次のように入力して、必要な特権を付与し、現在のセッションに適用します。

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

MySQLバックアップユーザーが構成され、必要なアクセス権があります。

バックアップ用のテストデータを作成する

次に、テストデータを作成します。 次のコマンドを実行して、 `+ equipment `テーブルで ` playground +`データベースを作成します。 青いスライドを表す単一のレコードを挿入することから始めます。

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

このガイドの後半では、このデータを使用および変更して、完全および増分バックアップを作成する能力をテストします。

MySQLセッションを終了する前に、 `+ datadir `変数の値を確認します。 システムレベルの ` backup +`ユーザーがMySQLデータファイルにアクセスできるようにするには、この値を知る必要があります。

次のように入力して、 `+ datadir +`変数の値を表示します。

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

見つけた場所をメモします。

これが現時点でMySQL内で行う必要があるすべてです。 次のように入力してシェルを終了します。

exit

次に、システムレベルの構成を見てみましょう。

Systems Backupユーザーの構成と権限の割り当て

バックアップを実行するMySQLユーザーができたので、同様の制限された権限を持つ対応するLinuxユーザーが存在することを確認します。

Ubuntu 16.04では、「+ backup 」ユーザーと対応する「 backup 」グループがすでに利用可能です。 次のコマンドで ` / etc / passwd `および ` / etc / group +`ファイルをチェックして、これを確認します。

grep backup /etc/passwd /etc/group
Output/etc/passwd:backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
/etc/group:backup:x:34:

`+ / etc / passwd `ファイルの1行目は ` backup `ユーザーを説明し、 ` / etc / group `ファイルの2行目は ` backup +`グループを定義しています。

MySQLデータが保存されている + / var / lib / mysql`ディレクトリは、 + mysql`ユーザーとグループが所有しています。 データベースファイルやディレクトリへのアクセスを安全に許可するために、 + backup`ユーザーを + mysql`グループに追加できます。 また、バックアップするファイルにアクセスできるように、「+ backup」グループに「+ sudo」ユーザーを追加する必要があります。

次のコマンドを入力して、「+ backup 」ユーザーを「 mysql」グループに追加し、「+ sudo」ユーザーを「+ backup +」グループに追加します。

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

`+ / etc / group `ファイルを再度チェックすると、現在のユーザーが ` backup `グループに追加され、 ` backup `ユーザーが ` mysql +`グループに追加されていることがわかります。

grep backup /etc/group
Outputbackup:x:34:
mysql:x:116:backup

新しいグループは、現在のセッションでは自動的に使用できません。 `+ sudo +`ユーザーが利用できるグループを再評価するには、ログアウトしてから再度ログインするか、次のように入力します。

exec su - ${USER}

続行するには、 `+ sudo `ユーザーのパスワードの入力を求められます。 ユーザーのグループをもう一度チェックして、現在のセッションが「 backup +」グループにアクセスできることを確認します。

id -nG
Output sudo backup

`+ sudo `ユーザーは ` backup +`グループのメンバーシップを利用できるようになります。

次に、グループの実行権限を追加して、 + / var / lib / mysql`ディレクトリとそのサブディレクトリを + mysql`グループがアクセスできるようにする必要があります。 そうしないと、 `+ mysql `グループのメンバーであっても、 ` backup +`ユーザーはこれらのディレクトリに入ることができません。

`+ mysql +`グループにMySQLデータディレクトリへのアクセスを許可するには、次のように入力します。

sudo find /var/lib/mysql -type d -exec chmod 750 {} \;

これで、 `+ backup +`ユーザーはMySQLディレクトリへのアクセスが必要になりました。

バックアップ資産の作成

MySQLおよびシステムバックアップユーザーが利用可能になったので、バックアップを正常に作成および保護するために必要な構成ファイル、暗号化キー、およびその他の資産のセットアップを開始できます。

バックアップパラメータを使用してMySQL構成ファイルを作成する

バックアップスクリプトが使用する最小限のMySQL構成ファイルを作成することから始めます。 これには、MySQLユーザーのMySQL資格情報が含まれます。

テキストエディタで `+ / etc / mysql / backup.cnf +`にあるファイルを開きます。

sudo nano /etc/mysql/backup.cnf

内部で、 `+ [client] +`セクションを開始し、MySQL内で定義したMySQLバックアップユーザーとパスワードユーザーを設定します。

/etc/mysql/backup.cnf

[client]
user=backup
password=

完了したら、ファイルを保存して閉じます。

ファイルの所有権を「+ backup +」ユーザーに付与し、他のユーザーがファイルにアクセスできないように権限を制限します。

sudo chown backup /etc/mysql/backup.cnf
sudo chmod 600 /etc/mysql/backup.cnf

バックアップユーザーはこのファイルにアクセスして適切な資格情報を取得できますが、他のユーザーは制限されます。

バックアップルートディレクトリを作成する

次に、バックアップコンテンツ用のディレクトリを作成します。 バックアップのベースディレクトリとして `+ / backups / mysql`を使用します。

sudo mkdir -p /backups/mysql

次に、 + / backups / mysql`ディレクトリの所有権を + backup + ユーザーに割り当て、グループの所有権を + mysql`グループに割り当てます。

sudo chown backup:mysql /backups/mysql

これで、 `+ backup +`ユーザーはバックアップデータをこの場所に書き込むことができます。

バックアップファイルを保護する暗号化キーを作成する

バックアップにはデータベースシステム自体からのすべてのデータが含まれているため、バックアップを適切に保護することが重要です。 `+ xtrabackup +`ユーティリティには、各ファイルをバックアップおよびアーカイブするときに暗号化する機能があります。 暗号化キーを提供するだけです。

`+ 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

このキーは、バックアッププロセス中およびバックアップから復元する必要があるときに使用されます。

バックアップおよび復元スクリプトの作成

これで、実行中のMySQLインスタンスの安全なバックアップを実行するために必要なものがすべて揃いました。

バックアップと復元の手順を繰り返し可能にするために、プロセス全体のスクリプトを作成します。 次のスクリプトを作成します。

  • + backup-mysql.sh +:このスクリプトはMySQLデータベースをバックアップし、プロセス内のファイルを暗号化および圧縮します。 完全および増分バックアップを作成し、コンテンツを日ごとに自動的に整理します。 デフォルトでは、スクリプトは3日間分のバックアップを維持します。

  • + extract-mysql.sh +:このスクリプトは、バックアップファイルを解凍および復号化して、バックアップされたコンテンツを含むディレクトリを作成します。

  • + prepare-mysql.sh +:このスクリプトは、ファイルを処理してログを適用することにより、バックアップディレクトリを「準備」します。 増分バックアップは完全バックアップに適用されます。 準備スクリプトが終了すると、ファイルをデータディレクトリに戻す準​​備が整います。

GitHubのこのチュートリアルのリポジトリでいつでもスクリプトを表示できます。 以下の内容をコピーして貼り付けたくない場合は、次のように入力してGitHubから直接ダウンロードできます。

cd /tmp
curl -LO https://raw.githubusercontent.com/do-community/ubuntu-1604-mysql-backup/master/backup-mysql.sh
curl -LO https://raw.githubusercontent.com/do-community/ubuntu-1604-mysql-backup/master/extract-mysql.sh
curl -LO https://raw.githubusercontent.com/do-community/ubuntu-1604-mysql-backup/master/prepare-mysql.sh

スクリプトをダウンロードした後、それらが正常に取得され、実行するアクションを承認することを確認してください。 満足したら、スクリプトを実行可能としてマークし、次を入力してそれらを `+ / usr / local / bin +`ディレクトリに移動します:

chmod +x /tmp/{backup,extract,prepare}-mysql.sh
sudo mv /tmp/{backup,extract,prepare}-mysql.sh /usr/local/bin

次に、これらの各スクリプトを設定し、それらについて詳しく説明します。

backup-mysql.shスクリプトを作成します

GitHubから `+ backup-mysql.sh `スクリプトをダウンロードしていない場合は、 ` backup-mysql.sh `という名前の新しいファイルを ` / usr / local / bin +`ディレクトリに作成します。

sudo nano /usr/local/bin/backup-mysql.sh

スクリプトの内容をコピーしてファイルに貼り付けます。

/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 [ "$(id --user --name)" != "$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 xtrabackup arguments
   xtrabackup_args=(
       "--defaults-file=${defaults_file}"
       "--backup"
       "--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"
   )

   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")
       xtrabackup_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
   xtrabackup "${xtrabackup_args[@]}" --target-dir="${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日間のバックアップが保持されます。 これは、スクリプト内で `+ days_of_backups +`パラメーターを調整することで変更できます。

スクリプトを実行すると、個々のバックアップを表すタイムスタンプ付きファイルが書き込まれる毎日のディレクトリが作成されます。 最初のタイムスタンプ付きファイルは、「+ full- 」というプレフィックスが付いた完全バックアップになります。 その日の後続のバックアップは、最後の完全バックアップまたは増分バックアップ以降の変更を表す、「 incremental- +」プレフィックスで示される増分バックアップになります。

バックアップは、最新のバックアップ操作からの出力とともに、毎日のディレクトリに「+ backup-progress.log 」というファイルを生成します。 最新のバックアップメタデータを含む「 xtrabackup_checkpoints 」というファイルもそこに作成されます。 このファイルは、将来の増分バックアップを作成するために必要なので、削除しないことが重要です。 追加のメタデータを含む「 xtrabackup_info +」というファイルも作成されますが、スクリプトはこのファイルを参照しません。

終了したら、ファイルを保存して閉じます。

次に、まだ実行していない場合は、次のように入力してスクリプトを実行可能にします。

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

MySQLバックアップを開始する単一のコマンドが利用可能になりました。

extract-mysql.shスクリプトを作成します

次に、 `+ extract-mysql.sh +`スクリプトを作成します。 これは、個々のバックアップファイルからMySQLデータディレクトリ構造を抽出するために使用されます。

リポジトリからスクリプトをダウンロードしていない場合は、 `+ / usr / local / bin `ディレクトリに ` extract-mysql.sh +`というファイルを作成して開きます:

sudo nano /usr/local/bin/extract-mysql.sh

内部に、次のスクリプトを貼り付けます。

/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}"

       xtrabackup_args=(
           "--parallel=${processors}"
           "--decrypt=AES256"
           "--encrypt-key-file=${encryption_key_file}"
           "--decompress"
       )

       xtrabackup "${xtrabackup_args[@]}" --target-dir="${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 "[email protected]"

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 !=  $# )); 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 `ディレクトリを作成し、引数として渡されたバックアップごとに個別のディレクトリを作成します。 アーカイブからディレクトリ構造を抽出し、その中の個々のファイルを復号化し、復号化されたファイルを解凍することにより、提供された ` .xbstream +`ファイルを処理します。

このプロセスが完了した後、 `+ restore +`ディレクトリには、提供された各バックアップのディレクトリが含まれている必要があります。 これにより、ディレクトリを調べ、バックアップの内容を調べ、準備および復元するバックアップを決定できます。

完了したら、ファイルを保存して閉じます。 その後、次のように入力して、スクリプトが実行可能であることを確認します。

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

このスクリプトにより、個々のバックアップファイルを復元に必要なディレクトリ構造に展開できます。

prepare-mysql.shスクリプトを作成します

最後に、 `+ / usr / local / bin `ディレクトリ内に ` prepare-mysql.sh +`スクリプトをダウンロードまたは作成します。 このスクリプトは、各バックアップにログを適用して、一貫性のあるデータベーススナップショットを作成します。 増分バックアップを完全バックアップに適用して、後の変更を組み込みます。

スクリプトファイルを以前にダウンロードしていない場合は、テキストエディターで作成します。

sudo nano /usr/local/bin/prepare-mysql.sh

内部に、次の内容を貼り付けます。

/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}"
   xtrabackup --prepare --apply-log-only --target-dir="${full_backup_dir}"

   for increment in "${incremental_dirs[@]}"; do
       printf "Applying incremental backup %s to %s\n" "${increment}" "${full_backup_dir}"
       xtrabackup --prepare --apply-log-only --incremental-dir="${increment}" --target-dir="${full_backup_dir}"
   done

   printf "Applying final logs to full backup %s\n" "${full_backup_dir}"
   xtrabackup --prepare --target-dir="${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} == ${#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 xtrabackup --copy-back --target-dir=${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のデータディレクトリに移動できる一貫したデータセットを表します。

データ損失の可能性を最小限に抑えるため、スクリプトはファイルをデータディレクトリにコピーするまで停止します。 この方法により、ユーザーはこのプロセス中に作成されたバックアップコンテンツとログファイルを手動で確認し、MySQLデータディレクトリの現在のコンテンツをどう処理するかを決定できます。 コマンドを終了すると、ファイルを完全に復元するために必要なコマンドが表示されます。

完了したら、ファイルを保存して閉じます。 以前にそうしなかった場合は、次のように入力してファイルを実行可能としてマークします。

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

このスクリプトは、バックアップファイルをMySQLのデータディレクトリに移動する前に実行する最終スクリプトです。

MySQLバックアップおよび復元スクリプトのテスト

バックアップおよび復元スクリプトがサーバー上にあるので、テストする必要があります。

完全バックアップを実行する

`+ backup `ユーザーで ` backup-mysql.sh +`スクリプトを呼び出すことから始めます:

sudo -u backup backup-mysql.sh
OutputBackup successful!
Backup created at /backups/mysql/Thu/full-04-20-2017_14-55-17.xbstream

すべてが計画どおりに進んだ場合、スクリプトは正しく実行され、成功を示し、新しいバックアップファイルの場所を出力します。 上記の出力が示すように、毎日のディレクトリ(この場合は「Thu」)は、その日のバックアップを格納するために作成されています。 バックアップファイル自体は、これが完全バックアップであることを表すために「+ full- +」で始まります。

毎日のバックアップディレクトリに移動して、コンテンツを表示しましょう。

cd /backups/mysql/"$(date +%a)"
ls
Outputbackup-progress.log  full-04-20-2017_14-55-17.xbstream  xtrabackup_checkpoints  xtrabackup_info

ここでは、実際のバックアップファイル(この場合は + full-04-20-2017_14-55-17.xbstream +)、バックアップイベントのログ( + backup-progress.log +)、 +バックアップされたコンテンツに関するメタデータを含むxtrabackup_checkpoints + `ファイル、および追加のメタデータを含む + xtrabackup_info + `ファイル。

`+ backup-progress.log +`を追跡すると、バックアップが正常に完了したことを確認できます。

tail backup-progress.log
Output170420 14:55:19 All tables unlocked
170420 14:55:19 [00] Compressing, encrypting and streaming ib_buffer_pool to <STDOUT>
170420 14:55:19 [00]        ...done
170420 14:55:19 Backup created in directory '/backups/mysql/Thu/'
170420 14:55:19 [00] Compressing, encrypting and streaming backup-my.cnf
170420 14:55:19 [00]        ...done
170420 14:55:19 [00] Compressing, encrypting and streaming xtrabackup_info
170420 14:55:19 [00]        ...done
xtrabackup: Transaction log of lsn (2549956) to (2549965) was copied.
170420 14:55:19

`+ xtrabackup_checkpoints +`ファイルを見ると、バックアップに関する情報を見ることができます。 このファイルは管理者にとって有用な情報を提供しますが、主に後続のバックアップジョブで使用され、既に処理されたデータを把握します。

これは、各アーカイブに含まれるファイルのコピーです。 このコピーは、最新の情報を表すために各バックアップで上書きされますが、各オリジナルはバックアップアーカイブ内で引き続き使用可能です。

cat xtrabackup_checkpoints
Outputbackup_type = full-backuped
from_lsn = 0
to_lsn = 2549956
last_lsn = 2549965
compact = 0
recover_binlog_info = 0

上記の例は、完全バックアップが取得され、バックアップがログシーケンス番号(LSN)0からログシーケンス番号2549956をカバーすることを示しています。 `+ last_lsn +`番号は、バックアッププロセス中に一部の操作が発生したことを示します。

増分バックアップを実行する

完全バックアップができたので、追加の増分バックアップを作成できます。 増分バックアップは、最後のバックアップが実行されてから行われた変更を記録します。 最初の増分バックアップは完全バックアップに基づいており、後続の増分バックアップは以前の増分バックアップに基づいています。

どのバックアップが適用されたかを確認できるように、別のバックアップを取る前にデータベースにデータを追加する必要があります。

10個の黄色のスイングを表す「+ playground 」データベースの「 equipment +」テーブルに別のレコードを挿入します。 このプロセス中に、MySQL管理パスワードの入力を求められます。

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

最新のバックアップよりも最新のデータがあるため、増分バックアップを行って変更をキャプチャできます。 同じ日の完全バックアップが存在する場合、 `+ backup-mysql.sh +`スクリプトは増分バックアップを取得します。

sudo -u backup backup-mysql.sh
OutputBackup successful!
Backup created at /backups/mysql/Thu/incremental-04-20-2017_17-15-03.xbstream

毎日のバックアップディレクトリを再度チェックして、増分バックアップアーカイブを見つけます。

cd /backups/mysql/"$(date +%a)"
ls
Outputbackup-progress.log                incremental-04-20-2017_17-15-03.xbstream  xtrabackup_info
full-04-20-2017_14-55-17.xbstream  xtrabackup_checkpoints

`+ xtrabackup_checkpoints +`ファイルの内容は、最新の増分バックアップを参照するようになりました。

cat xtrabackup_checkpoints
Outputbackup_type = incremental
from_lsn = 2549956
to_lsn = 2550159
last_lsn = 2550168
compact = 0
recover_binlog_info = 0

バックアップタイプは「増分」としてリストされ、フルバックアップのようにLSN 0から開始する代わりに、最後のバックアップが終了したLSNから開始します。

バックアップを抽出する

次に、バックアップファイルを抽出してバックアップディレクトリを作成します。 スペースとセキュリティの考慮事項により、これは通常、データを復元する準備ができたときにのみ行う必要があります。

`+ .xbstream `バックアップファイルを ` extract-mysql.sh `スクリプトに渡すことで、バックアップを抽出できます。 繰り返しますが、これは ` backup +`ユーザーが実行する必要があります。

sudo -u backup extract-mysql.sh *.xbstream
OutputExtraction complete! Backup directories have been extracted to the "restore" directory.

上記の出力は、プロセスが正常に完了したことを示しています。 毎日のバックアップディレクトリの内容を再度確認すると、 `+ extract-progress.log `ファイルと ` restore +`ディレクトリが作成されています。

抽出ログを追跡すると、最新のバックアップが正常に抽出されたことを確認できます。 他のバックアップ成功メッセージは、ファイルの前の方に表示されます。

tail extract-progress.log
Output170420 17:23:32 [01] decrypting and decompressing ./performance_schema/socket_instances.frm.qp.xbcrypt
170420 17:23:32 [01] decrypting and decompressing ./performance_schema/events_waits_summary_by_user_by_event_name.frm.qp.xbcrypt
170420 17:23:32 [01] decrypting and decompressing ./performance_schema/status_by_user.frm.qp.xbcrypt
170420 17:23:32 [01] decrypting and decompressing ./performance_schema/replication_group_members.frm.qp.xbcrypt
170420 17:23:32 [01] decrypting and decompressing ./xtrabackup_logfile.qp.xbcrypt
170420 17:23:33 completed OK!


Finished work on incremental-04-20-2017_17-15-03.xbstream

`+ restore +`ディレクトリに移動すると、抽出したバックアップファイルに対応するディレクトリが利用可能になります。

cd restore
ls -F
Outputfull-04-20-2017_14-55-17/  incremental-04-20-2017_17-15-03/

バックアップディレクトリには生のバックアップファイルが含まれていますが、MySQLがまだ使用できる状態ではありません。 これを修正するには、ファイルを準備する必要があります。

最終バックアップを準備する

次に、バックアップファイルを準備します。 そのためには、「+ full- 」および「 incremental- 」バックアップが含まれる「 restore 」ディレクトリにいる必要があります。 スクリプトは、すべての ` incremental- `ディレクトリからの変更を ` full- +`バックアップディレクトリに適用します。 その後、ログを適用して、MySQLが使用できる一貫したデータセットを作成します。

何らかの理由で変更の一部を復元したくない場合は、これらの増分バックアップディレクトリを `+ restore `ディレクトリから削除する最後の機会になります(増分バックアップファイルは親ディレクトリで引き続き使用可能です)。 現在のディレクトリ内の残りの「 incremental- 」ディレクトリは、「 full- +」バックアップディレクトリに適用されます。

準備ができたら、 `+ prepare-mysql.sh `スクリプトを呼び出します。 繰り返しますが、個々のバックアップディレクトリがある ` restore +`ディレクトリにいることを確認してください:

sudo -u backup prepare-mysql.sh
OutputBackup 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 xtrabackup --copy-back --target-dir=/backups/mysql/Thu/restore/full-04-20-2017_14-55-17

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

上記の出力は、バックアップが完全に準備されているとスクリプトが判断し、 `+ full- `バックアップが完全に一貫したデータセットを表すことを示しています。 出力の状態として、 ` prepare-progress.log +`ファイルをチェックして、プロセス中にエラーが報告されていないことを確認する必要があります。

スクリプトは、ファイルを実際にMySQLのデータディレクトリにコピーするまで停止するため、すべてが正しく見えることを確認できます。

バックアップデータをMySQLデータディレクトリに復元する

ログを確認した後、すべてが正常であることを確認したら、 `+ prepare-mysql.sh +`の出力で説明されている指示に従うことができます。

まず、実行中のMySQLプロセスを停止します。

sudo systemctl stop mysql

バックアップデータはMySQLデータディレクトリの現在の内容と競合する可能性があるため、 `+ / var / lib / mysql `ディレクトリを削除または移動する必要があります。 ファイルシステムにスペースがある場合、最良のオプションは何かがうまくいかない場合に現在のコンテンツを ` / tmp +`ディレクトリまたは他の場所に移動することです:

sudo mv /var/lib/mysql/ /tmp

空の `+ / var / lib / mysql`ディレクトリを作成します。 すぐにパーミッションを修正する必要があるので、まだ心配する必要はありません。

sudo mkdir /var/lib/mysql

これで、 `+ xtrabackup +`ユーティリティを使用して、完全バックアップをMySQLデータディレクトリにコピーできます。 以下のコマンドで、準備した完全バックアップへのパスを置き換えます。

sudo xtrabackup --copy-back --target-dir=/backups/mysql//restore/full-

コピー中のファイルの実行中のログがプロセス全体を通して表示されます。 ファイルが配置されたら、MySQLユーザーとグループが復元された構造を所有してアクセスできるように、所有権とアクセス許可を再度修正する必要があります。

sudo chown -R mysql:mysql /var/lib/mysql
sudo find /var/lib/mysql -type d -exec chmod 750 {} \;

復元されたファイルは、MySQLデータディレクトリにあります。

MySQLを再度起動してプロセスを完了します。

sudo systemctl start mysql

`+ playground.equipment`テーブルの内容を表示して、データが復元されたかどうかを確認します。 繰り返しますが、続行するにはMySQLの `+ root`パスワードの入力を求められます。

mysql -u root -p -e 'SELECT * FROM playground.equipment;'
Output+----+-------+-------+--------+
| id | type  | quant | color  |
+----+-------+-------+--------+
|  1 | slide |     2 | blue   |
|  2 | swing |    10 | yellow |
+----+-------+-------+--------+
2 rows in set (0.02 sec)

データが正常に復元されました。

データを復元した後、戻って `+ restore +`ディレクトリを削除することが重要です。 将来の増分バックアップは、完全バックアップが準備された後は完全バックアップに適用できないため、削除する必要があります。 さらに、セキュリティ上の理由から、バックアップディレクトリをディスク上で暗号化しないでください。

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

次にバックアップディレクトリのクリーンコピーが必要になったときに、バックアップファイルからそれらを再度抽出できます。

1時間ごとにバックアップを実行するためのCronジョブの作成

バックアップと復元プロセスがスムーズに機能していることを確認したので、定期的にバックアップを自動的に取得するために「+ cron +」ジョブを設定する必要があります。

`+ / etc / cron.hourly `ディレクトリ内に小さなスクリプトを作成して、バックアップスクリプトを自動的に実行し、結果を記録します。 ` cron +`プロセスはこれを1時間ごとに自動的に実行します:

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

内部では、出力がジャーナルで利用できるように、 `+ systemd-cat `ユーティリティでバックアップスクリプトを呼び出します。 ログを簡単にフィルタリングできるように、 ` backup-mysql`識別子でそれらをマークします:

/etc/cron.hourly/backup-mysql

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

完了したら、ファイルを保存して閉じます。 次を入力して、スクリプトを実行可能にします。

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

これで、バックアップスクリプトは1時間ごとに実行されます。 スクリプト自体は、3日前より古いバックアップのクリーンアップを処理します。

`+ cron +`スクリプトを手動で実行してテストできます:

sudo /etc/cron.hourly/backup-mysql

完了したら、次を入力してログメッセージのジャーナルを確認します。

sudo journalctl -t backup-mysql
Output-- Logs begin at Wed 2017-04-19 18:59:23 UTC, end at Thu 2017-04-20 18:54:49 UTC. --
Apr 20 18:35:07 myserver backup-mysql[2302]: Backup successful!
Apr 20 18:35:07 myserver backup-mysql[2302]: Backup created at /backups/mysql/Thu/incremental-04-20-2017_18-35-05.xbstream

数時間後にもう一度チェックして、追加のバックアップが取られていることを確認します。

結論

このガイドでは、Percona Xtrabackupツールをインストールして、MySQLデータのライブスナップショットを定期的に作成できるようにしました。 MySQLとシステムバックアップユーザーを構成し、バックアップファイルを保護するための暗号化キーを設定してから、バックアップおよび復元手順の一部を自動化するスクリプトを設定しました。

バックアップスクリプトは、毎日開始時にフルバックアップを生成し、その後1時間ごとに増分バックアップを生成し、いつでも3日間のバックアップを保持します。 暗号化されたファイルと暗号化キーを他のバックアップテクノロジーと組み合わせて使用​​し、保管のためにデータをオフサイトに転送できます。 抽出スクリプトと準備スクリプトにより、その日のバックアップをシステムの復元に使用できる一貫したデータのセットにまとめることができます。