序章

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

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

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

前提条件

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

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

MySQLがインストールされたら、サーバーにログインします。 sudo 続行するユーザー。

PerconaXtrabackupツールのインストール

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

まず、UbuntuPerconaリリースページにアクセスして、最新のものを見つけます .deb リポジトリをインストールするためのパッケージ。 コード名が「XenialXerus」であるUbuntu16.04を使用しているため、「xenial」パッケージを選択する必要があります。 対応するリンクを右クリックして、アドレスをコピーします。

注:次のように入力すると、いつでもサーバーのリリースコードネームを再確認できます。

  1. lsb_release -c
Output
Codename: xenial

リンクをコピーしたら、に移動します /tmp ディレクトリを作成し、リポジトリ構成パッケージをダウンロードします。 curl:

  1. cd /tmp
  2. curl -LO https://repo.percona.com/apt/percona-release_0.1-4.xenial_all.deb

次に、 dpkg ダウンロードしたパッケージをインストールします。これにより、Perconaが構成されます。 apt システム上のリポジトリ:

  1. sudo dpkg -i percona*

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

  1. sudo apt-get update
  2. sudo apt-get install percona-xtrabackup-24 qpress

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

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

まず、MySQLrootユーザーとの対話型MySQLセッションを開始します。

  1. mysql -u root -p

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

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

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

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

  1. CREATE USER 'backup'@'localhost' IDENTIFIED BY 'password';

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

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

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

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

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

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

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

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

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

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

あなたが見つけた場所をメモしてください。

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

  1. exit

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

システムバックアップユーザーの構成とアクセス許可の割り当て

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

Ubuntu 16.04では、 backup ユーザーと対応する backup グループはすでに利用可能です。 これを確認するには、 /etc/passwd/etc/group 次のコマンドでファイルを作成します。

  1. 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 ファイルには、 backup ユーザー、一方から2行目 /etc/group ファイルは backup グループ。

The /var/lib/mysql MySQLデータが保持されているディレクトリは、 mysql ユーザーとグループ。 追加できます backup ユーザーから mysql データベースファイルとディレクトリへのアクセスを安全に許可するグループ。 また、 sudo ユーザーから backup バックアップするファイルにアクセスできるようにグループ化します。

次のコマンドを入力して、 backup ユーザーから mysql グループとあなたの sudo ユーザーから backup グループ:

  1. sudo usermod -aG mysql backup
  2. sudo usermod -aG backup ${USER}

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

  1. grep backup /etc/group
Output
backup:x:34:sammy mysql:x:116:backup

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

  1. exec su - ${USER}

あなたはあなたのために促されます sudo 続行するにはユーザーのパスワード。 現在のセッションがアクセスできるようになったことを確認します backup ユーザーのグループを再度確認してグループ化します。

  1. id -nG
Output
sammy sudo backup

私たちの sudo これで、ユーザーはメンバーシップを利用できるようになります。 backup グループ。

次に、 /var/lib/mysql ディレクトリとそのサブディレクトリにアクセス可能 mysql グループ実行権限を追加してグループ化します。 それ以外の場合は、 backup ユーザーは、のメンバーであっても、これらのディレクトリに入ることができません。 mysql グループ。

注:の値が datadir ではなかった /var/lib/mysql 以前にMySQLの内部をチェックしたときは、次のコマンドで見つけたディレクトリに置き換えてください。

与えるために mysql MySQLデータディレクトリへのグループアクセス、次のように入力します。

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

私たちの backup これで、ユーザーはMySQLディレクトリに必要なアクセス権を取得できます。

バックアップ資産の作成

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

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

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

でファイルを開きます /etc/mysql/backup.cnf テキストエディタで:

  1. sudo nano /etc/mysql/backup.cnf

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

/etc/mysql/backup.cnf
[client]
user=backup
password=password

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

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

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

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

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

次に、バックアップコンテンツ用のディレクトリを作成します。 我々は使用するだろう /backups/mysql バックアップのベースディレクトリとして:

  1. sudo mkdir -p /backups/mysql

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

  1. sudo chown backup:mysql /backups/mysql

The backup これで、ユーザーはこの場所にバックアップデータを書き込めるようになります。

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

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

バックアップルートディレクトリ内に暗号化キーを作成できます。 openssl 指図:

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

このファイルへのアクセスも制限することが非常に重要です。 繰り返しますが、所有権をに割り当てます backup ユーザーおよび他のすべてのユーザーへのアクセスを拒否します。

  1. sudo chown backup:backup /backups/mysql/encryption_key
  2. sudo chmod 600 /backups/mysql/encryption_key

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

バックアップと復元のスクリプトの作成

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

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

  • backup-mysql.sh:このスクリプトはMySQLデータベースをバックアップし、プロセスでファイルを暗号化および圧縮します。 完全バックアップと増分バックアップを作成し、コンテンツを日ごとに自動的に整理します。 デフォルトでは、スクリプトは3日分のバックアップを維持します。
  • extract-mysql.sh:このスクリプトは、バックアップファイルを解凍および復号化して、バックアップされたコンテンツを含むディレクトリを作成します。
  • prepare-mysql.sh:このスクリプトは、ファイルを処理してログを適用することにより、バックアップディレクトリを「準備」します。 増分バックアップはすべて、完全バックアップに適用されます。 準備スクリプトが終了すると、ファイルをデータディレクトリに戻す準備が整います。

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

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

ダウンロード後にスクリプトを調べて、スクリプトが正常に取得されたこと、およびスクリプトが実行するアクションを承認していることを確認してください。 満足している場合は、スクリプトを実行可能としてマークしてから、スクリプトをに移動します /usr/local/bin 次のように入力してディレクトリを作成します。

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

次に、これらの各スクリプトを設定し、詳細に説明します。

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

ダウンロードしなかった場合 backup-mysql.sh GitHubからのスクリプト、で新しいファイルを作成します /usr/local/bin と呼ばれるディレクトリ backup-mysql.sh:

  1. 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 最新のバックアップ操作からの出力を含むdailyディレクトリにあります。 と呼ばれるファイル xtrabackup_checkpoints 最新のバックアップメタデータを含むものもそこに作成されます。 このファイルは将来の増分バックアップを作成するために必要なので、削除しないことが重要です。 と呼ばれるファイル xtrabackup_info追加のメタデータを含む、も生成されますが、スクリプトはこのファイルを参照しません。

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

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

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

これで、MySQLバックアップを開始する単一のコマンドを使用できるようになりました。

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

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

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

  1. 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 "$@"

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 ディレクトリには、提供された各バックアップのディレクトリが含まれている必要があります。 これにより、ディレクトリを調べ、バックアップの内容を調べ、準備および復元するバックアップを決定できます。

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

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

このスクリプトを使用すると、個々のバックアップファイルを復元に必要なディレクトリ構造に拡張できます。

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

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

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

  1. 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データディレクトリの現在の内容をどのように処理するかを決定できます。 コマンドを終了すると、ファイルを完全に復元するために必要なコマンドが表示されます。

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

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

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

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

バックアップと復元のスクリプトがサーバー上にあるので、それらをテストする必要があります。

フルバックアップを実行する

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

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

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

毎日のバックアップディレクトリに移動して、内容を確認しましょう。

  1. cd /backups/mysql/"$(date +%a)"
  2. ls
Output
backup-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、バックアップが正常に完了したことを確認できます。

  1. tail backup-progress.log
Output
170420 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 ファイル、バックアップに関する情報を表示できます。 このファイルは、管理者に役立つ情報を提供しますが、主に後続のバックアップジョブで使用されるため、管理者はどのデータが既に処理されているかを知ることができます。

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

  1. cat xtrabackup_checkpoints
Output
backup_type = full-backuped from_lsn = 0 to_lsn = 2549956 last_lsn = 2549965 compact = 0 recover_binlog_info = 0

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

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

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

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

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

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

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

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

毎日のバックアップディレクトリをもう一度確認して、増分バックアップアーカイブを見つけます。

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

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

  1. cat xtrabackup_checkpoints
Output
backup_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 ユーザー:

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

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

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

  1. tail extract-progress.log
Output
170420 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 ディレクトリ、抽出したバックアップファイルに対応するディレクトリが利用可能になりました。

  1. cd restore
  2. ls -F
Output
full-04-20-2017_14-55-17/ incremental-04-20-2017_17-15-03/

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

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

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

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

準備ができたら、 prepare-mysql.sh 脚本。 繰り返しますが、 restore 個々のバックアップディレクトリが配置されているディレクトリ:

  1. sudo -u backup prepare-mysql.sh
Output
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=/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プロセスを停止します。

  1. sudo systemctl stop mysql

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

  1. sudo mv /var/lib/mysql/ /tmp

空を再作成します /var/lib/mysql ディレクトリ。 すぐに権限を修正する必要があるので、まだ心配する必要はありません。

  1. sudo mkdir /var/lib/mysql

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

  1. sudo xtrabackup --copy-back --target-dir=/backups/mysql/Thu/restore/full-04-20-2017_14-55-17

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

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

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

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

  1. sudo systemctl start mysql

内容を確認して、データが復元されているか確認してください。 playground.equipment テーブル。 繰り返しますが、MySQLの入力を求められます root 続行するためのパスワード:

  1. 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 ディレクトリ。 将来の増分バックアップは、準備ができたら完全バックアップに適用できないため、削除する必要があります。 さらに、セキュリティ上の理由から、バックアップディレクトリをディスク上で暗号化せずに放置しないでください。

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

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

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

バックアップと復元のプロセスがスムーズに機能していることを確認したので、次の設定を行う必要があります。 cron 定期的なバックアップを自動的に作成するジョブ。

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

  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

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

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

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

テストできます cron 手動で実行してスクリプトを作成します。

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

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

  1. 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日間のバックアップを保持します。 暗号化されたファイルと暗号化キーを他のバックアップテクノロジーと組み合わせて使用して、データをオフサイトに転送して保管することができます。 抽出および準備スクリプトを使用すると、その日のバックアップを、システムの復元に使用できる一貫性のあるデータセットにまとめることができます。