序章
多くの場合、データベースはインフラストラクチャに最も価値のある情報の一部を格納します。 このため、事故やハードウェア障害が発生した場合のデータ損失を防ぐために、信頼性の高いバックアップを用意することが重要です。
Percona XtraBackupバックアップツールは、システムの実行中にMySQLデータの「ホット」バックアップを実行する方法を提供します。 これを行うには、ファイルシステムレベルでデータファイルをコピーしてから、クラッシュリカバリを実行して、データセット内の一貫性を実現します。
このガイドでは、Ubuntu16.04サーバー上のMySQLデータのバックアップを自動化するシステムを作成します。 スクリプトのグループでcronツールとPerconaツールを使用して、問題が発生した場合の回復に使用できる定期的で安全なバックアップを作成します。
前提条件
このガイドを完了するには、ルート以外のsudo
ユーザーが管理タスク用に構成されたUbuntu16.04サーバーが必要です。 「Ubuntu16.04でのサーバーの初期設定」ガイドに従って、サーバーでこれらの権限を持つユーザーを設定できます。
sudo
ユーザーを利用できるようになったら、MySQLをインストールする必要があります。 使用するパッケージに応じて、これらのガイドのいずれかを使用できます。 最初のガイドは、公式のUbuntuリポジトリを使い続けたい場合に適していますが、2番目のガイドは、より最新の機能が必要な場合に適しています。
- Ubuntu 16.04にMySQLをインストールする方法(Ubuntuリポジトリのデフォルトパッケージを使用)
- Ubuntu 16.04に最新のMySQLをインストールする方法(MySQLプロジェクトによって提供される更新されたパッケージを使用)
MySQLがインストールされたら、sudo
ユーザーとしてサーバーにログインして続行します。
PerconaXtrabackupツールのインストール
最初に行う必要があるのは、実際のPerconaバックアップユーティリティをインストールすることです。 プロジェクトは、パッケージにアクセスするためにMySQLサーバーに追加できる独自のリポジトリを維持しています。
まず、UbuntuのPerconaリリースページに移動して、リポジトリをインストールするための最新の.deb
パッケージを見つけます。 コードネーム「XenialXerus」のUbuntu16.04を使用しているため、「xenial」パッケージを選択する必要があります。 対応するリンクを右クリックして、アドレスをコピーします。
注:次のように入力すると、いつでもサーバーのリリースコードネームを再確認できます。
- lsb_release -c
OutputCodename: xenial
リンクをコピーしたら、/tmp
ディレクトリに移動し、curl
を含むリポジトリ構成パッケージをダウンロードします。
- cd /tmp
- curl -LO https://repo.percona.com/apt/percona-release_0.1-4.xenial_all.deb
次に、dpkg
を使用して、ダウンロードしたパッケージをインストールします。これにより、システムにPerconaapt
リポジトリが構成されます。
- sudo dpkg -i percona*
新しいリポジトリを構成したら、ローカルパッケージインデックスを更新して、新しく利用可能なパッケージに関する情報を取得します。 次に、リポジトリからXtraBackupツールとqpress
圧縮ユーティリティをインストールします。
- sudo apt-get update
- sudo apt-get install percona-xtrabackup-24 qpress
バンドルされている他のユーティリティの中でも、xtrabackup
、xbstream
、およびqpress
コマンドが使用可能になります。 スクリプトは、これらのそれぞれを使用して、バックアップを実行し、データを復元します。
MySQLバックアップユーザーの構成とテストデータの追加
まず、MySQLrootユーザーとの対話型MySQLセッションを開始します。
- mysql -u root -p
MySQLのインストール中に選択した管理者パスワードの入力を求められます。 パスワードを入力すると、MySQLセッションに移動します。
適切な権限を持つMySQLユーザーを作成する
最初に行う必要があるのは、バックアップタスクを処理するように構成された新しいMySQLユーザーを作成することです。 このユーザーには、システムの実行中にデータを安全にコピーするために必要な権限のみが付与されます。
アカウントの目的を明確にするために、新しいユーザーをbackup
と呼びます。 ユーザーの資格情報を安全なファイルに配置するので、複雑なパスワードを自由に選択してください。
- CREATE USER 'backup'@'localhost' IDENTIFIED BY 'password';
次に、新しい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
次に、いくつかのシステムレベルの構成を見てみましょう。
システムバックアップユーザーの構成とアクセス許可の割り当て
バックアップを実行する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
グループに追加して、データベースファイルとディレクトリへのアクセスを安全に許可できます。 また、sudo
ユーザーをbackup
グループに追加して、バックアップするファイルにアクセスできるようにする必要があります。
次のコマンドを入力して、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:sammy
mysql:x:116:backup
新しいグループは、現在のセッションでは自動的に利用できません。 sudo
ユーザーが利用できるグループを再評価するには、ログアウトして再度ログインするか、次のように入力します。
- exec su - ${USER}
続行するには、sudo
ユーザーのパスワードの入力を求められます。 ユーザーのグループをもう一度確認して、現在のセッションがbackup
グループにアクセスできるようになったことを確認します。
- id -nG
Outputsammy sudo backup
sudo
ユーザーは、backup
グループのメンバーシップを利用できるようになります。
次に、グループ実行権限を追加して、/var/lib/mysql
ディレクトリとそのサブディレクトリにmysql
グループからアクセスできるようにする必要があります。 そうしないと、backup
ユーザーは、mysql
グループのメンバーであっても、これらのディレクトリに入ることができなくなります。
注:以前にMySQLの内部をチェックしたときに、datadir
の値が/var/lib/mysql
でなかった場合は、次のコマンドで見つけたディレクトリに置き換えてください。
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バックアップユーザーとパスワードユーザーを設定します。
[client]
user=backup
password=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
スクリプトをダウンロードしなかった場合は、/usr/local/bin
ディレクトリにbackup-mysql.sh
という名前の新しいファイルを作成します。
- sudo nano /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
というファイルをdailyディレクトリに生成します。 最新のバックアップメタデータを含む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
内部に、次のスクリプトを貼り付けます。
#!/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 "$@"
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
中に、次の内容を貼り付けます。
#!/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 completed OK!
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
番号は、バックアッププロセス中に一部の操作が発生したことを示します。
増分バックアップを実行する
これで完全バックアップができたので、追加の増分バックアップを取ることができます。 増分バックアップは、最後のバックアップが実行されてから行われた変更を記録します。 最初の増分バックアップは完全バックアップに基づいており、後続の増分バックアップは前の増分バックアップに基づいています。
どのバックアップが適用されたかを確認できるように、別のバックアップを作成する前にデータベースにデータを追加する必要があります。
playground
データベースのequipment
テーブルに、10個の黄色のスイングを表す別のレコードを挿入します。 このプロセス中に、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/Thu/restore/full-04-20-2017_14-55-17
コピーされているファイルの実行ログは、プロセス全体で表示されます。 ファイルを配置したら、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
テーブルの内容を表示して、データが復元されているかどうかを確認してください。 ここでも、続行するためにMySQLroot
パスワードの入力を求められます。
- 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
識別子でマークを付けます。
#!/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
数時間後にもう一度チェックして、追加のバックアップが作成されていることを確認してください。
結論
このガイドでは、MySQLデータのライブスナップショットを定期的に作成するのに役立つPerconaXtrabackupツールをインストールしました。 MySQLとシステムのバックアップユーザーを構成し、バックアップファイルを保護するための暗号化キーを設定してから、バックアップと復元の手順の一部を自動化するスクリプトを設定しました。
バックアップスクリプトは、毎日の開始時に完全バックアップを生成し、その後は1時間ごとに増分バックアップを生成し、いつでも3日間のバックアップを保持します。 暗号化されたファイルと暗号化キーを他のバックアップテクノロジーと組み合わせて使用して、データをオフサイトに転送して保管することができます。 抽出および準備スクリプトを使用すると、その日のバックアップを、システムの復元に使用できる一貫したデータセットにまとめることができます。