2026年7月3日

2026年7月3日

LVMスナップショットでライブバックアップを実行する手順(MySQL・WordPress対応)

LVM スナップショットを使うと、サービスを止めずに「ある瞬間のディスクの状態」を固定し、そこから落ち着いてバックアップを取れます。手順は「空き容量を確認する」「スナップショットを作る」「読み取り専用でマウントしてコピーする」「すぐに削除する」の4段階です。この記事では、WordPress と MySQL が動いているサーバーを例に、データベースの整合性を保つ方法、スナップショットがあふれたときの挙動、後片付けまで含めたスクリプトを説明します。

LVM スナップショットの仕組みと注意点

LVM(Logical Volume Manager)のスナップショットは、作成した瞬間の論理ボリューム(LV)の状態を参照できる仮想的なボリュームです。中身を丸ごと複製するのではなく、元の LV でブロックが書き換えられるときに、書き換え前のデータをスナップショット領域へ退避する copy-on-write(CoW)方式で動きます。そのため作成は数秒で終わり、最初はほとんど容量を使いません。

ただし、次の点を理解しておく必要があります。

  • スナップショット自体はバックアップではない:同じディスク上にあるため、ディスクが壊れれば一緒に失われます。スナップショットはあくまで「静止した状態からコピーするための足場」です。
  • 領域があふれると使えなくなる:通常の(シック)スナップショットでは、確保したサイズを超えて変更が発生すると、そのスナップショットは無効になります。
  • 存在している間は書き込みが遅くなる:CoW のぶん元の LV への書き込みに負荷がかかるため、コピーが終わったらすぐ削除します。

手順1:構成と空き容量を確認する

スナップショット用の領域は、元の LV と同じボリュームグループ(VG)の空き領域から確保します。まず現状を確認します。

sudo vgs
sudo lvs -o lv_name,vg_name,lv_size,origin,data_percent
df -hT

vgs の VFree がスナップショットに使える空き容量です。ここが 0 だと作成できません。クラウドや VPS の初期構成では VG の空きがないことが多く、その場合は先にディスクを追加して VG を拡張する必要があります。

スナップショットのサイズは、バックアップにかかる時間のあいだに元の LV へ書き込まれる量を見積もって決めます。アクセスの少ない時間帯に数十分で終わるなら、元の LV の 10〜20% 程度から始め、後述の使用率を見ながら調整するのが現実的です。

df -hT ではファイルシステムの種類(ext4 か XFS か)も確認しておきます。マウント時のオプションが変わるためです。

手順2:データベースの整合性を考える

LVM スナップショットの作成時には、デバイスが一時停止され、ファイルシステムも凍結(freeze)されるため、ファイルシステムとしては整合性のとれた状態になります。ただし MySQL のようにメモリ上にデータを持つアプリケーションから見ると、これは「電源を突然切った直後」と同じ状態(クラッシュ整合)です。

InnoDB はクラッシュリカバリの仕組みを持つので、データディレクトリと InnoDB のログが同じ LV にあれば、多くの場合はそのまま起動できます。それでも確実性を上げたい場合は、スナップショットを作る数秒だけ書き込みを止めます。FLUSH TABLES WITH READ LOCK は、ロックをかけたセッションが切れると解除されるため、同じセッションの中でスナップショットを作る必要があります。mysql クライアントの system コマンドを使うと、それができます。

sudo mysql <<'SQL'
FLUSH TABLES WITH READ LOCK;
system lvcreate --size 5G --snapshot --name lv_data_snap /dev/vg0/lv_data
UNLOCK TABLES;
SQL

ロック中はサイトへの書き込み(コメント投稿や管理画面での保存など)が待たされます。スナップショットの作成は通常すぐ終わりますが、長時間かかるクエリが走っているとロックの取得自体が待たされることがあるため、実行時間帯を選んでください。データベースを止めずに論理バックアップを取る方法として、mysqldump の --single-transaction を併用するのもよい選択です。

手順3:スナップショットを作ってマウントする

データベースのロックが不要な場合は、lvcreate を直接実行します。

sudo lvcreate --size 5G --snapshot --name lv_data_snap /dev/vg0/lv_data
sudo lvs

lvs の出力で、lv_data_snap の Origin 欄に lv_data が表示されていれば成功です。

次に、スナップショットを読み取り専用でマウントします。ファイルシステムによって指定が異なります。

sudo mkdir -p /mnt/snap

# ext4 の場合
sudo mount -o ro /dev/vg0/lv_data_snap /mnt/snap

# XFS の場合(元のボリュームと UUID が同じなので nouuid が必要)
sudo mount -o ro,nouuid /dev/vg0/lv_data_snap /mnt/snap

XFS で nouuid を付け忘れると、元のボリュームと UUID が重複しているためにマウントが失敗します。ext4 でジャーナルに関するエラーが出る場合は、ro,noload を試すとジャーナルを再生せずにマウントできます。

手順4:外部へコピーして、すぐに削除する

マウントしたスナップショットから、別のディスクや別サーバーへコピーします。rsync、tar、restic、borg など、普段使っているツールで構いません。

sudo rsync -aHAX --delete /mnt/snap/ backup@backup-host:/srv/backup/web01/

コピーが終わったら、アンマウントしてスナップショットを削除します。

sudo umount /mnt/snap
sudo lvremove -y /dev/vg0/lv_data_snap

削除を忘れて放置すると、元の LV の書き込み性能が下がり続け、いずれ領域があふれて無効になります。途中でエラーになっても後片付けが行われるよう、スクリプトでは trap で終了時の処理を登録しておくのが定石です。

手順5:スクリプトにまとめる

#!/usr/bin/env bash
# /usr/local/bin/lvm-snap-backup.sh
set -euo pipefail

VG="vg0"
LV="lv_data"
SNAP="${LV}_snap"
SIZE="5G"
MNT="/mnt/snap"
DEST="backup@backup-host:/srv/backup/web01/"

cleanup() {
  mountpoint -q "$MNT" && umount "$MNT" || true
  lvs "${VG}/${SNAP}" >/dev/null 2>&1 && lvremove -y "${VG}/${SNAP}" || true
}
trap cleanup EXIT

mkdir -p "$MNT"

mysql <<SQL
FLUSH TABLES WITH READ LOCK;
system lvcreate --size ${SIZE} --snapshot --name ${SNAP} /dev/${VG}/${LV}
UNLOCK TABLES;
SQL

# ext4 の例。XFS なら -o ro,nouuid
mount -o ro "/dev/${VG}/${SNAP}" "$MNT"

rsync -aHAX --delete "${MNT}/" "$DEST"

# 使用率を記録しておくと、サイズの見直しに使える
lvs -o lv_name,data_percent "${VG}/${SNAP}"

echo "lvm snapshot backup ok: $(date '+%F %T')"

root の crontab に flock -n 付きで登録し、ログをファイルへ残します。初回はログの data_percent を見て、コピー終了時点でスナップショットがどのくらい埋まっていたかを確認してください。50% を大きく超えるようならサイズを増やします。

スナップショットがあふれないようにする

lvs の Data% 列(環境によっては Snap%)が上限に達すると、そのスナップショットは無効になり、マウントしていても読み出せなくなります。元の LV のデータは影響を受けませんが、その回のバックアップは失敗です。

/etc/lvm/lvm.conf の activation セクションにある snapshot_autoextend_threshold と snapshot_autoextend_percent を設定すると、使用率がしきい値を超えたときに自動で拡張されます。この機能は dmeventd による監視が有効になっていることが前提で、VG に空きがなければ拡張できません。設定項目の既定値や説明は LVM2 のバージョンで異なることがあるため(2026年10月現在)、手元の lvm.conf に書かれたコメントもあわせて確認してください。自動拡張に頼りきらず、見積もりに余裕を持たせるのが基本です。

シンプロビジョニングの場合と、ロールバックとしての使い方

シンプール上の LV(シン LV)では、lvcreate --snapshot --name snap vg0/thin_lv のようにサイズを指定せずにスナップショットを作れます。シンスナップショットは既定で起動時に有効化されない設定(activation skip)になっているため、マウントする前に lvchange -ay -K vg0/snap で有効化します。シンプール自体の空きがなくなると元の LV にも影響するので、lvs でプールの使用率を監視してください。

また、lvconvert --merge vg0/lv_data_snap を使うと、元の LV をスナップショット作成時点へ巻き戻せます。OS やミドルウェアの更新前に取っておくと、失敗時の切り戻しに使えます。元の LV が使用中の場合、マージは次回の有効化時(多くは再起動時)に行われます。巻き戻しは作成後の変更をすべて失う操作なので、実行前に必要なデータを退避してください。

まとめ

  • LVM スナップショットは CoW で瞬時に作れるが、それ自体はバックアップではなく、コピーのための足場
  • 作成前に vgs で VG の空きを確認し、バックアップ時間中の書き込み量からサイズを決める
  • MySQL は FLUSH TABLES WITH READ LOCK と mysql クライアントの system を組み合わせると整合性を高められる
  • XFS は ro,nouuid でマウントし、コピー後は trap を使って漏れなく削除する
  • Data% を監視し、必要なら自動拡張の設定や lvconvert --merge によるロールバックも活用する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲