Categories
Database Backup

** Discover how DevOps engineers and DBAs can detect corrupted database backups before disaster strikes. Learn advanced techniques for PostgreSQL, SQL Server, and MySQL, including automated restore testing and checksum validation.

データベース管理とサイト信頼性エンジニアリング(SRE)というハイステークスな世界には、よく知られた公理があります。それが「シュレーディンガーのバックアップ」です。バックアップの状態は、復元を試みるまで不明です。その瞬間まで、バックアップは「完全に有効である」状態と「完全に破損している」状態の量子的な重ね合わせの中に存在しています。

DevOpsエンジニアやDBAにとって、インシデント発生中に重要なデータベースのバックアップが破損していることを発見するのは、最悪の悪夢です。それは、日常的な復旧作業を壊滅的なデータ損失イベントへと変えてしまいます。このデータの整合性における「静かなる殺人者」は、バックアップジョブがペイロードの破損時であっても頻繁に終了コード 0(成功)を報告するため、見過ごされがちです。

本ガイドでは、バックアップ破損の構造を解剖し、データベース固有の検証手法を探り、本番環境向けに自動化された堅牢な復元パイプラインを構築する方法を解説します。

バックアップ破損の構造

破損を検出するには、まずそれがどのように発生するかを理解する必要があります。バックアップの破損は一般的に、物理的(インフラレベル)と論理的(アプリケーションレベル)の2つのカテゴリに分類されます。

物理的破損

物理的破損は、ストレージメディア上の実際のビットが変更されたときに発生します。これは、ソースディスクからの読み取りプロセス中、ネットワーク転送中、またはターゲットストレージでの静止中に発生する可能性があります。
* ビット腐敗(Bit Rot): ストレージメディアの経年劣化により、ビットが静かに反転することがあります。
* 転送エラー: TCPにはチェックサムがありますが、その能力は非常に限定的(16ビット)です。高スループット環境では、TCPで検知できないデータ破損が転送中に発生する可能性があります。
* ストレージコントローラーの障害: RAIDコントローラーやSANファブリックのハードウェアバグにより、OSには成功と報告しながら、実際にはゴミデータが書き込まれることがあります。

論理的破損

論理的破損は、バックアップファイル自体は完全に無傷であるにもかかわらず、内部のデータが壊れているため、より危険と言えます。
* ゴミを入れたらゴミが出る(GIGO): 稼働中のデータベースに破損したインデックスや破損したページがある場合、バックアップツールは忠実にその破損したページをコピーします。バックアップジョブは成功しますが、復元は失敗するか、壊れたデータベースが生成されます。
* 不完全なトランザクション: データベースのI/Oを適切にフリーズさせずに(例:MySQLでFLUSH TABLES WITH READ LOCKを使用せずに)ファイルシステムレベルのスナップショットを取得すると、ページが不整合を起こし、復旧不可能な状態になります。

プロアクティブな検出:チェックサムと暗号学的ハッシュ

物理的破損に対する第一の防衛線は、暗号学的な検証です。ファイルサイズや更新日時に頼るだけでは不十分です。

データベースレベルのチェックサムの有効化

現代のリレーショナルデータベース管理システム(RDBMS)は、ページレベルのチェックサムをサポートしています。これを有効にすると、データベースはディスクに書き込む前に各ページのチェックサムを計算します。ページが読み取られる際(クエリやバックアッププロセスによる)、チェックサムが検証されます。

PostgreSQLの場合、クラスターの初期化時にデータチェックサムを有効にできます:

# チェックサムを有効にして新しいPostgreSQLクラスターを初期化
initdb --data-checksums -D /var/lib/postgresql/data

注:既存のPostgreSQLクラスターがある場合は、pg_checksumsユーティリティを使用してオフラインで有効にできます。

Microsoft SQL Serverの場合、PAGE_VERIFYCHECKSUMに設定されていることを確認してください(最新バージョンではデフォルトですが、レガシーシステムでは確認が必要です):

ALTER DATABASE [ProductionDB] SET PAGE_VERIFY CHECKSUM;
GO

保存データの検証

バックアップがストレージターゲットに到達したら、その整合性を暗号学的に検証する必要があります。CloudSaveのようなエンタープライズバックアッププラットフォームは、転送中および保存時にバックアップブロックのSHA-256ハッシュを自動的に計算・検証します。カスタムスクリプトを管理している場合は、これを手動で実装する必要があります:

# バックアップ作成後にSHA-256ハッシュを生成
sha256sum prod_db_backup.tar.gz > prod_db_backup.tar.gz.sha256

# ストレージサーバー上でハッシュを検証
sha256sum -c prod_db_backup.tar.gz.sha256

データベース固有の検証手法

各データベースエンジンは、バックアップ成果物の整合性を検証するためのネイティブツールを提供しています。

PostgreSQL: pg_verifybackup

PostgreSQL 13で導入されたpg_verifybackupは、pg_basebackupで取得された物理バックアップにとって画期的なツールです。バックアップ中に生成されたbackup_manifestファイルを読み取り、すべてのファイルが存在し、チェックサムが一致していることを検証します。

# 物理ベースバックアップディレクトリに対して検証を実行
pg_verifybackup /mnt/backups/postgres/base_backup_20231025/

データファイルのいずれかで1ビットでも反転していれば、pg_verifybackupは致命的なエラーをスローし、監視システムが直ちにDBAチームにアラートを送信できるようにします。

Microsoft SQL Server: RESTORE VERIFYONLY

SQL Serverは、実際に復元することなくバックアップファイルの物理的な整合性を検証するネイティブコマンドを提供しています。これはバックアップヘッダーをチェックし、ページチェックサムを検証します(バックアップ時に有効にされていた場合)。

RESTORE VERIFYONLY 
FROM DISK = 'Z:BackupsProdDB_Full.bak' 
WITH CHECKSUM;

警告: RESTORE VERIFYONLYは、バックアップファイルが読み取り可能であり、物理チェックサムが一致していることのみを確認します。論理的な整合性を保証するものではありません。論理的な整合性を確保するには、完全な復元を実行し、DBCC CHECKDBを実行する必要があります。

MySQL / InnoDB: Percona XtraBackup

MySQL環境では、物理バックアップはPercona XtraBackupによって処理されることが一般的です。バックアッププロセスはファイルのコピーで構成されますが、トランザクションログ(REDOログ)が適用されるまでバックアップは整合性を持ちません。--prepareフェーズが組み込みの整合性チェックとして機能します。

# バックアップの準備(prepare)によりREDOログが適用されます。
# バックアップが破損している場合、このステップは失敗します。
xtrabackup --prepare --target-dir=/data/backups/mysql/

ゴールドスタンダード:自動復元テスト

チェックサムや検証コマンドは必要ですが、それだけでは不十分です。バックアップが有効であることを確実に証明する唯一の方法は、実際に復元することです。現代のDevOps環境では、このプロセスを完全に自動化する必要があります。

バックアップをコードとして扱うことで、データベース復元のCI/CDパイプラインを構築できます。このパイプラインは、一時的なインフラをプロビジョニングし、復元を実行し、検証クエリを実行し、環境を破棄する一連の流れを自動化します。

自動復元パイプラインの構築

以下は、PostgreSQLの論理ダンプを検証するために、cronジョブやCIランナー(GitLab CIやGitHub Actionsなど)から毎日トリガーできるBashスクリプトの例です。

#!/bin/bash
set -e

BACKUP_FILE="/mnt/storage/prod_db_latest.dump"
DB_NAME="prod_db"
CONTAINER_NAME="pg_restore_test"

echo "[INFO] 自動復元テストを開始します..."

# 1. 一時的なPostgreSQLコンテナを起動
docker run --name $CONTAINER_NAME 
  -e POSTGRES_PASSWORD=testpass 
  -d postgres:15

# PostgreSQLの準備ができるまで待機
echo "[INFO] データベースの初期化を待機中..."
until docker exec $CONTAINER_NAME pg_isready -U postgres; do
  sleep 2
done

# 2. ターゲットデータベースを作成
docker exec $CONTAINER_NAME psql -U postgres -c "CREATE DATABASE $DB_NAME;"

# 3. 復元を実行
echo "[INFO] バックアップを復元中..."
docker cp $BACKUP_FILE $CONTAINER_NAME:/tmp/backup.dump
docker exec $CONTAINER_NAME pg_restore -U postgres -d $DB_NAME -1 /tmp/backup.dump

# 4. 論理検証クエリを実行
echo "[INFO] 検証クエリを実行中..."
# usersテーブルに10,000件以上のレコードがあるか確認
USER_COUNT=$(docker exec $CONTAINER_NAME psql -U postgres -d $DB_NAME -t -c "SELECT COUNT(*) FROM users;")

if [ "$USER_COUNT" -lt 10000 ]; then
    echo "[ERROR] 論理検証失敗。10,000ユーザー以上を期待していましたが、$USER_COUNT件でした。"
    # ここでPagerDuty / Slackアラートをトリガー
    exit 1
else
    echo "[SUCCESS] 論理検証成功。ユーザー数: $USER_COUNT"
fi

# 5. 一時環境を破棄
echo "[INFO] クリーンアップ中..."
docker rm -f $CONTAINER_NAME

echo "[INFO] 自動復元テストが正常に完了しました。"

何を検証すべきか?

自動復元テストを実行する際は、データベースが起動するかどうかを確認するだけでなく、アプリケーション固有の検証クエリを実行してください:
1. 行数: 主要なテーブルが期待通りの行数を持っているか確認する(例:usersテーブルが空ではないこと)。
2. 最新データ: 過去24時間以内に作成されたレコードをクエリし、バックアップが古くないことを確認する。
3. 参照整合性: 孤立した外部キーがないかチェックするスクリプトを実行する(論理的破損の兆候)。

バックアップ異常の監視とアラート

災害が発生する前に破損を検出するには、堅牢なオブザーバビリティが必要です。バイナリの成功/失敗状態を超えて、バックアップジョブのメタデータを監視し、異常を検出する必要があります。

ヒューリスティック監視

バックアップのメタデータをPrometheusに統合し、Grafanaで可視化します。以下のヒューリスティックに対してアラートを設定してください:
* 急激なサイズ減少: 日々のバックアップが常に500GBであるのに、今日が50MBであれば、ジョブは成功(終了コード0)していても、空のスキーマをバックアップした可能性があります。
* 所要時間の異常: 通常2時間かかるバックアップが5分で終わる場合、何かがスキップされています。逆に10時間かかる場合は、ディスクI/Oの劣化により破損につながる可能性があります。
* WAL/アーカイブログの蓄積: データベースが先行書き込みログ(WAL)を生成しているのに、バックアップシステムが十分にアーカイブできていない場合、ポイントインタイムリカバリ(PITR)チェーンに欠落が生じるリスクがあります。

整合性チェックを伴う3-2-1ルールの実装

業界標準の3-2-1バックアップルール(データのコピーを3つ、2つの異なるメディアに、1つをオフサイトに)は、すべてのコピーが検証されている場合にのみ有効です。

ここでCloudSaveのようなエンタープライズソリューションを活用することで、運用オーバーヘッドを大幅に削減できます。すべてのデータベースノードに対して複雑なbashスクリプトを記述・保守する代わりに、CloudSaveはインフラと直接統合して3-2-1ライフサイクルを自動化します。ランサムウェアから保護するイミュータブル(不変)ストレージを提供し、組み込みの自動復元検証スケジュールを備えています。CloudSaveは自動的に分離されたサンドボックス環境を立ち上げ、バックアップをマウントし、カスタムSQL検証スクリプトを実行し、ヘルスステータスを中央ダッシュボードに報告できます。

結論

破損したデータベースバックアップは、ビジネスを破壊しかねない静かなる殺人者です。バックアップスクリプトの終了コード 0だけに頼るのは危険な賭けです。

本番環境を真に保護するには、多層防御戦略を採用する必要があります:
1. データベースエンジン内でページレベルのチェックサムを有効にする。
2. バックアップ作成直後にネイティブ検証ツール(pg_verifybackupRESTORE VERIFYONLY)を活用する。
3. バックアップのメタデータ(サイズ、所要時間)を監視し、ヒューリスティックな異常を検知する。
4. 日々の運用パイプラインの一部として、自動化された一時的な復元テストを実装する。

受動的な「バックアップして忘れる」という考え方から、能動的な「継続的な復元検証」モデルへと移行することで、災害が避けられない事態となった際にも、データが準備されており、信頼性が高く、完全に復旧可能であることを保証できます。