Categories
Database Backup

> Discover why standard VM snapshots cause data corruption in transactional databases like PostgreSQL and SQL Server. Learn DBA best practices for application-consistent backups, avoiding VM stun, and ensuring data integrity with CloudSave.

DevOpsエンジニアやシステム管理者にとって、仮想マシン(VM)のスナップショットは基本的なツールです。これは、リスクの高いパッチ適用、大規模な構成変更、またはアプリケーションのデプロイを行う前に、サーバーの状態を迅速かつ便利に保存する手段を提供します。万が一問題が発生しても、数秒でロールバックが可能です。

しかし、この手法をPostgreSQL、MySQL、Oracle、Microsoft SQL Serverなどのトランザクションデータベースに適用すると、VMスナップショットは安全装置から「時限爆弾」へと変貌します。

データベースのバックアップに標準的なハイパーバイザーのスナップショットを頼ることは、データの破損、ページ破損(torn pages)、および復旧不可能な本番環境の停止を引き起こす最も一般的な原因の一つです。本記事では、ハイパーバイザーとデータベースエンジンの間にあるアーキテクチャ上の衝突、スナップショット中のデータ破損のメカニズム、そして仮想化されたデータベースを安全にバックアップするために必要なエンジニアリングのベストプラクティスについて解説します。

アーキテクチャの衝突:ハイパーバイザー vs. データベースエンジン

なぜVMスナップショットがデータベースを危険にさらすのかを理解するために、まずは両方のシステムがどのように状態とI/O操作を管理しているかを確認する必要があります。

ハイパーバイザーはどのようにスナップショットを実行するか

ハイパーバイザー(VMware ESXi、Microsoft Hyper-V、KVMなど)がスナップショットを取得する際、ディスクをコピーするわけではありません。その代わりに、現在の仮想ディスクファイル(例:.vmdk.vhdx)を読み取り専用状態に固定し、新しいデルタディスク(差分ディスク)を作成します。それ以降の書き込みはすべて、このデルタディスクに向けられます。

スナップショットが削除されると、ハイパーバイザーはデルタディスクのデータをベースディスクにコミット(統合)しなければなりません。標準的なスナップショットは、ゲストOS内で実行されているアプリケーションを全く認識していません。スナップショットは、そのマイクロ秒時点でのディスク状態をそのままキャプチャします。

トランザクションデータベースはどのように状態を管理するか

トランザクションデータベースは、ACID特性(原子性、一貫性、独立性、永続性)に基づいて設計されています。ACID準拠を維持しつつ高いパフォーマンスを実現するために、データベースはすべてのトランザクションを即座にディスク上のプライマリデータファイルへ直接書き込むことはしません。その代わり、複雑な多層アーキテクチャを使用しています:

  1. バッファプール / 共有バッファ: データはシステムメモリ内で読み込まれ、変更されます。
  2. 先行書き込みログ(WAL) / Redoログ: 永続性を確保するため、変更内容はディスク上の高度に最適化されたログファイルに順次書き込まれます。
  3. チェックポイント / Lazy Writer: 定期的に、メモリ内の変更された(ダーティ)ページをディスク上の実際のデータファイルへフラッシュします。

このアーキテクチャのため、ディスク上の物理データファイルは、データベースの実際の状態と同期が取れていないことがほとんどです。データベースの真の状態は、ディスク上のデータファイル、WAL/Redoログ、そして現在メモリ上に存在するデータの組み合わせによってのみ存在します。

危険地帯:VMスナップショット中に何が起こるか

データベースサーバーの標準的なVMスナップショットを取得する場合、それはクラッシュ整合性(crash-consistent)のある状態をキャプチャしていることになります。

クラッシュ整合性とアプリケーション整合性

クラッシュ整合性のあるスナップショットは、物理サーバーの電源コードを突然引き抜くのと同じです。ディスクの状態はキャプチャされますが、メモリ内にあったものは失われ、ストレージコントローラーへ向かっていた途中のデータは突然遮断されます。

現代のデータベースは先行書き込みログをリプレイすることで予期せぬ電源断から復旧するように設計されていますが、クラッシュリカバリを主要なバックアップ戦略として頼ることは非常に危険です。データベースが複数の仮想ディスクにまたがっている場合(例:データファイルがドライブD:、WALがドライブE:)、ハイパーバイザーが両方のディスクを全く同じマイクロ秒でスナップショットするとは限りません。もしWALディスクのスナップショットがデータディスクのスナップショットよりわずかでも遅れて取得された場合、復元時にデータベースはシーケンス番号を照合できず、致命的な破損を引き起こします。

高トランザクションシステムにおける「VMスタンの影響」

スナップショットの作成プロセス、そしてさらに重要なスナップショットの統合プロセスは、「VMスタン(VM Stun)」として知られる現象を引き起こします。

I/Oをベースディスクからデルタディスクへ安全に切り替えるために、ハイパーバイザーは仮想マシンを一時的に停止(スタン)させる必要があります。負荷の低いWebサーバーであれば、このスタンは10〜50ミリ秒程度で済み、気づかれないかもしれません。しかし、膨大なI/Oを伴う高スループットのデータベースでは、大きなデルタディスクの統合によってVMが数秒間停止することがあります。

VMスタン中には以下のようなことが起こります:
* ネットワーク接続が切断され、アプリケーションのタイムアウトが発生する。
* 高可用性クラスター(SQL Server Always On、PostgreSQL Patroni、MySQL Galeraなど)がハートビートチェックを見逃す。
* クラスターがスタンしたノードを「死亡」と判断し、不要で破壊的なフェイルオーバー(スプリットブレインシナリオ)を引き起こす。

ページ破損とI/Oの不整合

データベースエンジンは通常、特定のページサイズ(PostgreSQLやSQL Serverでは8KB、InnoDBでは16KBなど)でデータを書き込みます。しかし、基盤となるOSやストレージアレイは、より小さなブロック(4KBや512バイトなど)でI/Oを処理します。

ハイパーバイザーがデータベースによる8KBページの書き込み中にスナップショットを取得すると、新しいデータの最初の4KBと古いデータの最後の4KBをキャプチャしてしまう可能性があります。これがページ破損(torn page)を引き起こします。スナップショットを復元しようとすると、データベースはページを読み込みますが、チェックサム検証に失敗し、データベースを破損状態としてマークします。

特定のデータベースエンジンにおける現実的な影響

データベースエンジンごとにクラッシュ整合性のあるスナップショットへの反応は異なりますが、本番環境において適切に処理できるものは一つもありません。

  • PostgreSQL: PostgreSQLはpg_walディレクトリに大きく依存しています。スナップショットがデータディレクトリ($PGDATA)とWALを同期せずにキャプチャした場合、PostgreSQLは起動に失敗し、PANIC: could not locate a valid checkpoint recordというエラーをスローします。
  • MySQL/InnoDB: InnoDBはページ破損を防ぐためにダブルライトバッファを使用しており、クラッシュ整合性のある状態に対してある程度の保護を提供します。しかし、ibdata1ファイルとib_logfileが同期せずにキャプチャされた場合、InnoDBエンジンはリカバリ時にクラッシュします。
  • Microsoft SQL Server: SQL ServerはI/Oのフリーズに対して非常に敏感です。適切なVSS(ボリュームシャドウコピーサービス)の統合なしに標準的なVMスナップショットからSQL Serverを復元すると、データベースが「suspect(疑わしい)」状態になり、ログチェーンが破損して、ポイントインタイムリカバリ(PITR)機能が失われることがよくあります。

仮想化されたデータベースを安全にバックアップするためのベストプラクティス

トランザクションデータベースを保護するには、クラッシュ整合性のあるバックアップからアプリケーション整合性(application-consistent)のあるバックアップへ移行する必要があります。これには、バックアップメカニズムがデータベースエンジンと通信し、スナップショット取得中にメモリをディスクへフラッシュさせ、I/O操作を一時的に停止させる必要があります。

1. アプリケーション対応の静止(VSSおよびfsfreeze)を活用する

Windowsの場合(SQL Server):
バックアップソリューションがMicrosoftボリュームシャドウコピーサービス(VSS)を利用していることを常に確認してください。VSS対応のバックアップがトリガーされると、SQL Server VSS WriterがデータベースのI/Oをフリーズし、保留中のトランザクションをディスクにフラッシュして、スナップショットが完全にアプリケーション整合性を保つようにします。

Linuxの場合(PostgreSQL / MySQL):
LinuxにはVSSに相当するネイティブ機能はありません。アプリケーション整合性を実現するには、ハイパーバイザーのゲストツール(VMware Toolsなど)と連携して、プリフリーズ(pre-freeze)およびポストソウ(post-thaw)スクリプトを使用する必要があります。

以下は、PostgreSQL 15以降でスナップショット用にデータベースを安全に準備するためのVMware pre-freeze-scriptの例です:

#!/bin/bash
# /usr/sbin/pre-freeze-script
# このスクリプトが実行可能であることを確認してください (chmod +x)

# 1. PostgreSQLにバックアップの準備を指示
su - postgres -c "psql -c "SELECT pg_backup_start('vm_snapshot', true);""

# 2. ファイルシステムのバッファをディスクにフラッシュ
sync

# 3. ファイルシステムをフリーズ (データが /var/lib/pgsql にあると仮定)
fsfreeze -f /var/lib/pgsql

そして、操作を再開するための対応するpost-thaw-scriptです:

#!/bin/bash
# /usr/sbin/post-thaw-script

# 1. ファイルシステムのフリーズを解除
fsfreeze -u /var/lib/pgsql

# 2. PostgreSQLにバックアップ完了を通知
su - postgres -c "psql -c "SELECT pg_backup_stop();""

2. ネイティブのデータベースバックアップユーティリティを使用する

アプリケーション整合性のあるスナップショットは標準的なスナップショットより優れていますが、依然としてVMスタンのリスクを伴います。データベースバックアップにとって最も安全なアプローチは、ハイパーバイザーから独立して動作するネイティブのストリーミングバックアップユーティリティを使用することです。

PostgreSQL (pg_basebackup):

pg_basebackup -h localhost -U replication_user -D /mnt/backups/pg_backup -Ft -z -P

MySQL/MariaDB (Percona XtraBackup / Mariabackup):
これらのツールは、データファイルをコピーしながらRedoログの変更を追跡することで、ブロッキングなしのホットバックアップを取得します。

mariabackup --backup --target-dir=/mnt/backups/mysql_backup --user=root --password=SecurePass

SQL Server (T-SQL):

BACKUP DATABASE [ProductionDB] 
TO DISK = N'Z:BackupsProductionDB.bak' 
WITH NOFORMAT, NOINIT, NAME = N'ProductionDB-Full Backup', 
SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10;
GO

3. ログアーカイブによるポイントインタイムリカバリ(PITR)の実装

日次のスナップショットやフルバックアップは、取得した時点までのデータしか保護しません。午後4時にデータベースがクラッシュし、最後のスナップショットが午前2時だった場合、14時間分のトランザクションデータが失われます。

真のエンタープライズレベルの回復力を実現するには、アプリケーション整合性のあるフルバックアップと、継続的なログアーカイブ(数分ごとにWAL、Redoログ、またはトランザクションログをバックアップする)を組み合わせる必要があります。これにより、DBAは災害発生前の特定の分、あるいは特定のトランザクションIDまでデータベースを復元できるようになります。

CloudSaveによるエンタープライズバックアップ戦略

数十台のデータベースサーバーにわたるカスタムのプリフリーズスクリプト、ネイティブダンプ用のcronジョブ、ログシッピングを管理することは、DevOpsチームにとって運用上の悪夢です。ここで、CloudSaveのようなエンタープライズグレードのプラットフォームが不可欠となります。

CloudSaveは、仮想化とデータベースアーキテクチャの間のギャップを埋めます。盲目的なハイパーバイザーのスナップショットに頼るのではなく、CloudSaveはSQL Server、PostgreSQL、MySQL、Oracleとネイティブに統合するアプリケーション対応エージェントを利用します。

CloudSaveがバックアップを開始すると:
1. ネイティブAPI(Windowsの場合はVSS、Linuxの場合はネイティブWALストリーミングなど)を介してデータベースエンジンと直接通信します。
2. 破壊的なVMスタンを引き起こすことなく、メモリバッファからディスクへのフラッシュを調整します。
3. データファイルを安全にキャプチャし、トランザクションログの切り捨てを自動的に管理します。
4. トランザクションログを継続的にバックアップし、数回のクリックで詳細なポイントインタイムリカバリ(PITR)を可能にします。

アプリケーション整合性の複雑さをCloudSaveにオフロードすることで、DBAやシステム管理者は、本番クラスターのパフォーマンスや可用性を犠牲にすることなく、データの整合性を保証できます。

結論

仮想マシンのスナップショットはインフラ管理のための素晴らしいツールですが、トランザクションデータベースのACID要件とは根本的に互換性がありません。クラッシュ整合性のあるハイパーバイザーのスナップショットに頼ることは、組織をページ破損、レプリケーションチェーンの断絶、そして壊滅的なデータ損失の危険にさらすことになります。

ミッションクリティカルなデータを保護するには、アプリケーション対応の静止機能を実装し、ネイティブのデータベースバックアップ手法を活用し、継続的なトランザクションログアーカイブを維持する必要があります。目的別に構築されたエンタープライズバックアップソリューションを採用することで、データベースの可用性を高く保ち、完全に復旧可能で、完全に安全な状態を確保できます。