2026年10月9日
2026年10月9日
MySQLバックアップからリストア
はじめに
データベース運用において「バックアップを取っている」ことと「いつでも確実にリストアできる」ことは全く別の話です。リストア手順を本番障害発生時に初めて試すような運用は最悪のシナリオで、論理破損や設定ミスで肝心の場面でデータが戻せない事故は今でも頻繁に起きています。
MySQLのリストアには、論理バックアップ(mysqldump)を読み込む方式と、物理バックアップ(Percona XtraBackup)を展開する方式があります。さらにバイナリログを併用すれば、任意の時刻まで戻すポイントインタイムリカバリ(PITR)も可能です。
本記事では、最も使われるmysqldumpからのリストアを中心に、xtrabackupとPITRの具体的な手順、そしてリストア前後で実施すべき検証チェックまで網羅して解説します。
症状・背景
- 誤ってDELETE/UPDATEを発行しテーブル全件を壊してしまった
- 数日前の状態に戻したいが手順書が無く判断に迷う
- 大容量DBでmysqldumpリストアに時間がかかり過ぎる
- バイナリログを使って事故直前の時刻まで復旧したい
手順・設定方法
ステップ1: バックアップファイルを確認
リストア前にダンプの整合性を確認します。
# ダンプファイルのサイズと先頭を確認
ls -lh /backup/mysql/dump-2026-05-14.sql.gz
zcat /backup/mysql/dump-2026-05-14.sql.gz | head -20
# 末尾に正常な完了マーカーがあるか確認
zcat /backup/mysql/dump-2026-05-14.sql.gz | tail -5
# MD5ハッシュで破損チェック
md5sum /backup/mysql/dump-2026-05-14.sql.gz
# 圧縮整合性を検証
gzip -t /backup/mysql/dump-2026-05-14.sql.gz && echo OK
ステップ2: 論理バックアップからのリストア
mysqldumpファイルを流し込みます。
# 既存DBをバックアップ(リストア失敗時の復旧用)
mysqldump --single-transaction --routines -u root -p \
--databases myapp > /tmp/myapp-before-restore.sql
# 対象DBを削除して再作成
mysql -u root -p -e "DROP DATABASE IF EXISTS myapp; CREATE DATABASE myapp CHARACTER SET utf8mb4;"
# 圧縮ダンプを直接ストリームで投入
zcat /backup/mysql/dump-2026-05-14.sql.gz | mysql -u root -p myapp
# 件数チェック
mysql -u root -p -e "SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.tables WHERE TABLE_SCHEMA='myapp';"
ステップ3: 物理バックアップからの高速リストア
XtraBackupで取得した物理バックアップを使います。
# 準備(prepare)フェーズでクラッシュリカバリ
sudo xtrabackup --prepare --target-dir=/backup/xtra/2026-05-14
# MySQLを停止
sudo systemctl stop mysql
# 既存データディレクトリを退避
sudo mv /var/lib/mysql /var/lib/mysql.old
# データファイルをコピーバック
sudo xtrabackup --copy-back --target-dir=/backup/xtra/2026-05-14
# 所有権を修正してMySQL起動
sudo chown -R mysql:mysql /var/lib/mysql
sudo systemctl start mysql
ステップ4: バイナリログでポイントインタイムリカバリ
ダンプ取得時刻以降の更新を再生します。
# 利用可能なバイナリログを確認
mysql -u root -p -e "SHOW BINARY LOGS;"
# 事故発生直前(例:2026-05-14 13:25:00)まで再生
sudo mysqlbinlog --start-datetime="2026-05-14 03:00:00" \
--stop-datetime="2026-05-14 13:25:00" \
/var/log/mysql/mysql-bin.000123 /var/log/mysql/mysql-bin.000124 \
| mysql -u root -p myapp
# 復旧確認(対象テーブルの件数を確認)
mysql -u root -p -e "SELECT COUNT(*) FROM myapp.orders;"
# 整合性チェック
mysqlcheck --all-databases -u root -p
注意事項
- リストア中はアプリケーション接続を必ず止める(中途半端な書き込みを防ぐ)
- リストア前に既存データを必ず別名で退避する
--single-transactionで取得していないダンプはトランザクション一貫性が無い- バイナリログのフォーマットは
ROW形式が安全(STATEMENTは非決定的SQLで誤差発生)
まとめ
1. 整合性検証 はリストア前の必須ステップ
2. 既存DBの退避 で失敗時の二段構え
3. 物理バックアップ は大容量DBで圧倒的に高速
4. PITR にはバイナリログとダンプ取得位置の記録が鍵
5. 定期リストア訓練 こそ最大の保険
関連記事: