LVMスナップショットを使用してMySQLデータベースをDigitalOcean Spacesにバックアップする方法

前書き

定期的なデータベースバックアップは、意図しないデータ損失イベントから保護するための重要なステップです。 効果的なバックアップおよびリカバリ戦略の設計には、多くの場合、パフォーマンスへの影響、実装コスト、およびデータストレージコストとリカバリ速度、データ整合性、およびバックアップカバレッジのトレードオフが伴います。 最適なソリューションは、リカバリポイントと時間objectives、およびデータベースの規模とアーキテクチャによって異なります。

このガイドでは、LVMスナップショットを使用して、実行中のMySQLデータベースのライブ(または「ホット」)物理バックアップを実行する方法を示します。 次に、データを圧縮してDigitalOcean Spaceに保存します。

このチュートリアルで説明する手順は、大規模なMySQLデータベース、ストレージエンジン(InnoDB、TokuDB、MyISAMなど)を混合して使用するデータベース、およびLVMを使用して管理される複数のブロックストレージボリュームを備えたデータベースサーバーに適しています。

Ubuntu 16.04サーバーがLVMスナップショットを取得してマウントできることを確認することから始めます。 次に、MySQLのデータディレクトリを含む論理ボリュームのLVMスナップショットを取得します。 次に、このスナップショットボリューム(凍結した論理ボリューム)をマウントし、MySQLデータディレクトリを圧縮してDigitalOcean Spacesに保存します。 最後に、サンプルの回復シナリオを簡単に説明します。

前提条件

このガイドを使用するには、次の前提条件を満たしている必要があります。

このすべてを設定したら、このガイドから始める準備ができました。

[[step-1 -—- investigate-mysql-and-lvm-configuration]] ==ステップ1—MySQLとLVMの構成を調査する

まず、MySQLデータディレクトリを見つけて、LVM設定に関する詳細を書き留めます。

MySQLdatadirを見つけます

MySQLデータディレクトリへのパスを見つけるには、次のコマンドを実行します。

mysqladmin -u root -p variables | grep datadir

プロンプトが表示されたら、MySQLrootパスワードを入力します。 次のような出力が表示されます。

Output| datadir                                                  | /data/mysql/

このガイドで使用されているMySQLインストールの場合、データディレクトリは/data/mysqlです。

ここで、/data/mysqlがLVM論理ボリューム上に存在することを確認する必要があります。 これを確認するために、lsblkを実行します。

lsblk

次のような出力が表示されます。

OutputNAME             MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda                8:0    0   600G  0 disk
└─vg1-mysql_data 252:0    0   475G  0 lvm  /data
vda              253:0    0   160G  0 disk
├─vda1           253:1    0 159.9G  0 part /
├─vda14          253:14   0     4M  0 part
└─vda15          253:15   0   106M  0 part /boot/efi

このことから、/dataが実際にはmysql_dataと呼ばれるLVM論理ボリュームのマウントポイントであることがわかります。 これは、ボリュームグループvg1のメンバーです。

ここで、LVMスナップショットを作成するのに十分な空き領域がボリュームグループvg1にあることを確認する必要があります。

LVM構成の調査

このセクションで説明するコマンドからの出力は、サーバーのハードウェアとLVMの構成によって異なることに注意することが重要です。 このガイドで使用するUbuntu 16.04サーバーのハードウェアとLVMの構成を簡単に調べてみましょう。

まず、pvscanを使用している物理ボリュームの数を調べてみましょう。

sudo pvscan

次のような出力が表示されます。

Output  PV /dev/sda   VG vg1             lvm2 [500.00 GiB / 25.00 GiB free]
  Total: 1 [500.00 GiB] / in use: 1 [500.00 GiB] / in no VG: 0 [0   ]

1つのボリュームグループ(vg1)に1つの500GB物理ボリューム(/dev/sda)があることがわかります。 この物理ボリュームの475GBは論理ボリュームに割り当てられていますが、25GBはボリュームグループが使用できるように空きがあります。

これは、vgdisplayコマンドを使用してvg1ボリュームグループを詳しく調べることで確認できます。

sudo vgdisplay

次のような出力が表示されます。

Output--- Volume group ---
  VG Name               vg1
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  2
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               500.00 GiB
  PE Size               4.00 MiB
  Total PE              127999
  Alloc PE / Size       121600 / 475.00 GiB
  Free  PE / Size       6399 / 25.00 GiB
  VG UUID               KEsoDE-zON7-NdyO-ioxb-6FSl-CB4m-S3QCRj

Alloc PE / SizeおよびFree PE / Size行から、475GBが割り当てられ、vg1ボリュームグループに25GBが空いていることがわかります。 Cur PV行は、このボリュームグループに1つの物理ボリュームがあることを示しています。 Cur LV行は、このボリュームグループのスペースのプールを使用して1つの論理ボリュームを作成したことを示しています。

ここで、lvdisplayを使用してこの論理ボリュームを見てみましょう。

sudo lvdisplay

次のような出力が表示されます。

Output  --- Logical volume ---
  LV Path                /dev/vg1/mysql_data
  LV Name                mysql_data
  VG Name                vg1
  LV UUID                T98x9c-zvC1-f0Rw-4ipn-Cxo2-duwk-KUwQQc
  LV Write Access        read/write
  LV Creation host, time LVM, 2018-04-18 20:11:48 +0000
  LV Status              available
  # open                 1
  LV Size                475.00 GiB
  Current LE             121600
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:0

LV Sizeから、/dev/vg1/mysql_dataに475GBの論理ボリュームmysql_dataが1つあることがわかります(vg1mysql_dataのボリュームグループの名前であったことを思い出してください)。

要約すると、このチュートリアルで使用したUbuntu 16.04サーバーには、1つのボリュームグループ(vg1)をバックアップするために使用される1つの500GB物理ボリューム(/dev/sda)があり、そこから単一の475GB論理ボリュームを作成しましたボリューム(mysql_data)。 これにより、ボリュームグループに25GBの空きスペースが残り、これを使用してさらに論理ボリューム(およびスナップショット)を作成できます。

ハードウェアとLVMの構成は異なる可能性があります。複数のブロックストレージデバイスを接続し、単一または複数のボリュームグループにプールすることができます。 それでも、特定の論理ボリュームのスナップショットを取得する手順は同じです。

このセクションで説明する一連のコマンドを使用すると、LVMとハードウェア構成の一般的な感覚が得られます。

次のステップでは、LVMスナップショット用にデータベースサーバーを準備します。

[[step-2 -—- prepare-your-server-for-lvm-snapshots]] ==ステップ2—サーバーをLVMスナップショット用に準備する

LVMスナップショットを安全に取得できるようにするには、バックアップおよびSpacesへのファイル転送中に発生する可能性のある書き込みまたは変更をカバーするのに十分なディスク容量をプロビジョニングする必要があります。 データベースのサイズによっては、このバックアップが完了するまでに数時間かかる場合があるため、ここで注意してください。 バックアップの実行中にスナップショットボリュームの容量が不足すると、スナップショットボリュームが無効になり、一貫性のあるバックアップができなくなります。

前のステップで、主要な論理ボリューム(mysql_data)を含むボリュームグループ(vg1)の空き容量が25GBしかないことを確認しました。 データベースのバックアップに要する時間内に25GBの変更がディスクに書き込まれない場合もありますが、理想的には少なくとも100GBの安全マージンが必要です。 実稼働環境では、スケジュールされたバックアップウィンドウ中にディスクに書き込まれるデータの平均量を測定し、それに応じてスナップショットボリュームサイズをスケーリングするのがベストプラクティスです。

vg1ボリュームグループに75GBのスペースを追加するには、ブロックストレージデバイスを接続するか、現在ドロップレットに接続されているボリュームのサイズを大きくします。 このチュートリアルでは、すでに接続されているブロックストレージボリュームを拡張します。追加のブロックストレージボリュームの接続について詳しくは、An Introduction to DigitalOcean Block Storageを参照してください。

[.note]#Note:一部のリージョンはまだブロックストレージをサポートしておらず、ブロックストレージボリュームをドロップレットに接続できない場合があります。 この場合の合理的な回避策は、ドロップレットのスナップショットを作成し、このスナップショットイメージを使用して新しいドロップレットを作成し、それにブロックストレージを追加することです。

このドロップレットに接続されているブロックストレージボリュームを拡張しましょう。

DigitalOceanのウェブコントロールパネルに移動し、ダッシュボードからドロップレットに移動します。

サイドバーで、Volumesをクリックします。

Sidebar

このペインから、ドロップレットに接続されているブロックストレージボリュームが表示されます。 このガイドで使用されているUbuntuドロップレットには、ブロックストレージボリュームが1つ添付されています。

Block Storage Volume

Moreをクリックしてから、Resize volumeをクリックします。

ここから、いくつかの定義済みボリュームサイズのいずれかを選択するか、独自のボリュームサイズを選択できます。 500GBのボリュームを100GBから600GBに増やしましょう:

Resize Volume

Continueを押します。 接続されたブロックストレージボリュームが100GB増加しました。

このデバイスの変更をLVMに伝播するには、pvresizeを実行する必要があります。

サーバーにログインし、pvscanを再度実行して、物理ボリュームをスキャンします。

sudo pvscan

/dev/sdaの物理ボリュームについては、以前と同じ出力が表示されるはずです。

Output PV /dev/sda   VG vg1             lvm2 [500.00 GiB / 25.00 GiB free]
  Total: 1 [500.00 GiB] / in use: 1 [500.00 GiB] / in no VG: 0 [0   ]

次に、ボリュームでpvresizeを実行して、追加したばかりの余分なスペースを埋めます。

sudo pvresize /dev/sda

次のような出力が表示されるはずです。

OutputPhysical volume "/dev/sda" changed
1 physical volume(s) resized / 0 physical volume(s) not resized

別のpvscanを実行して、物理ボリュームが100GB大きくなったことを確認しましょう。

sudo pvscan

/dev/sdaの物理ボリュームが600GBになったことを確認します。

Output PV /dev/sda   VG vg1             lvm2 [600.00 GiB / 125.00 GiB free]
 Total: 1 [600.00 GiB] / in use: 1 [600.00 GiB] / in no VG: 0 [0   ]

ボリュームグループの空き容量も100 GB増加したことを確認しましょう。

sudo vgdisplay

次の出力が表示されます。

Output  --- Volume group ---
  VG Name               vg1
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               600.00 GiB
  PE Size               4.00 MiB
  Total PE              153599
  Alloc PE / Size       121600 / 475.00 GiB
  Free  PE / Size       31999 / 125.00 GiB
  VG UUID               KEsoDE-zON7-NdyO-ioxb-6FSl-CB4m-S3QCRj

これは、スナップショットボリュームを作成するための空き容量が125GBになったことを示しています。

このチュートリアルの目的上、125GBはバックアップおよびアップロード手順中に書き込みと変更を吸収するのに十分ですが、実稼働設定では、バックアップウィンドウ中に予想されるディスク使用量に比例してスナップショットボリュームサイズをスケーリングする必要があります。

スナップショットおよびバックアップ中に発生する可能性のある書き込みまたは変更をカバーするのに十分なスペースがボリュームグループに使用できるようになったので、スナップショットボリュームの作成に進みます。

[[step-3 -—- create-and-mount-lvm-snapshot]] ==ステップ3—LVMスナップショットを作成してマウントする

[.warning]#Warning: LVMスナップショットがアクティブな間、ディスクへの書き込み時にパフォーマンスが低下します。 最初に、負荷をシミュレートした非本番データベースを使用してこの手順をテストし、このメソッドが本番デプロイメントで機能することを確認する必要があります。

次に、lvcreateを使用してmysql_data論理ボリュームのスナップショットを作成します。 これを行う前に、データの整合性を保証できるように、FLUSH TABLES WITH READ LOCKを使用してデータベースへの書き込みをフリーズする必要があります。 テーブルは、lvcreateを実行するまで読み取りロックする必要があります。実行すると、ロックを解除できます。 この一連のコマンドをスクリプト化する場合、現在実行中の書き込みクエリに応じて、合計ロック時間は非常に短くなります。

MySQLデータベースのロックの読み取り

テーブルをフラッシュすることから始めましょう。 データベースサーバーのターミナルから、mysqlを使用してMySQLデータベースにログインします。

mysql -u root -p

MySQLシェルから、FLUSH TABLESコマンドを実行して、データベースを読み取りロックします。

[.warning]#Warning:次のコマンドを実行すると、開いているすべてのテーブルが閉じられ、すべてのデータベースのすべてのテーブルがグローバル読み取りロックでロックされます。 これを本番データベースで実行する場合は、このコマンドをレプリカで実行するか、スクリプトの一部として実行して、データベースがロックされる時間を最小限に抑えることをお勧めします。

FLUSH TABLES WITH READ LOCK;

次のような出力が表示されるはずです。

OutputQuery OK, 0 rows affected (0.00 sec)

これは、データベースが読み取りロックされたことを示します。 MySQLプロンプトを終了しないでください。開いたままにしておく必要があります。

次に、MySQLデータを格納するために使用される論理ボリュームのLVMスナップショットを作成してマウントします。

スナップショットボリュームの作成とマウント

このMySQLクライアント接続を開いたまま、新しいターミナルウィンドウからデータベースサーバーにログインします。

[.warning]#Warning:この接続を閉じると、ロックが破棄されて書き込みが再開され、スナップショットの一貫性が失われます。

これで、mysql_data論理ボリュームのスナップショットを撮ることができます。 物理的なバックアップを実行する際に、書き込みやその他の変更を吸収するために、100GBのバッファースペースを割り当てます。 LVMスナップショットを作成するには、次のlvcreateコマンドを実行します。

sudo lvcreate -L 100G -s -n mysql_data_snap /dev/vg1/mysql_data

-Lフラグは、論理ボリュームのサイズ(この場合は100GB)を指定します。 -sは、論理ボリュームがスナップショットになることを示します。この場合は、/dev/vg1/mysql_data論理ボリュームです。 このスナップショットボリュームにmysql_data_snapという名前を付けることにしました。

次の結果が表示されます。

OutputLogical volume "mysql_data_snap" created.

これは、バックアップを実行できるmysql_data論理ボリュームのコピーがあることを示しています。

ある時点で基本的にMySQLデータファイルを「凍結」したので、データベーステーブルのロックを解除して書き込みを再開できます。 開いているMySQL接続から、次のコマンドを実行します。

UNLOCK TABLES;

次の結果が表示されます。

OutputQuery OK, 0 rows affected (0.00 sec)

テーブルのロックが解除され、この接続を安全に閉じることができます。

この時点で、データベースはまだ稼働しており、着信接続と書き込みを受け入れていますが、FLUSH TABLES WITH READ LOCKを実行した時点(または完全に正確に言えば、その時点)でのデータの一貫したスナップショットがあります。 FLUSHが完了した後の最後の書き込みクエリ)。

最後の手順では、このスナップショットをマウントして、これらの凍結データファイルにアクセスできるようにします。

まず、/backup_srcというマウントポイントを作成します。

sudo mkdir /backup_src

次に、スナップショットボリュームを/backup_srcにマウントします。

sudo mount /dev/vg1/mysql_data_snap /backup_src

これで、凍結されたデータファイルにアクセスできます。 見てみましょう:

cd /backup_src
ls

MySQLデータディレクトリが表示されます。

Outputlost+found  mysql

データの一貫したスナップショットにアクセスできるようになったので、それをDigitalOcean Spaceにバックアップできます。

[[step-4 -—- compress-and-upload-files-to-digitalocean-spaces]] ==ステップ4—ファイルを圧縮してDigitalOceanスペースにアップロードする

このバックアップをDigitalOceanSpaceにアップロードするには、prerequisite stepsにインストールして構成したs3cmdツールを使用します。

最初にs3cmd構成をテストし、バックアップスペースへのアクセスを試みます(このチュートリアルでは、スペースの名前はmysql-backup-demoです)。

s3cmd info s3://mysql-backup-demo/

次のような出力が表示されるはずです。

Outputs3://mysql-backup-demo/ (bucket):
   Location:  nyc3
   Payer:     BucketOwner
   Expiration Rule: none
   Policy:    none
   CORS:      none
   ACL:       3587522: FULL_CONTROL

この出力は、接続が成功し、s3cmdがオブジェクトをスペースに転送できることを示しています。

次に、MySQLデータディレクトリを圧縮してmysql-backup-demoスペースにアップロードします。

sudo tar -czvf - /backup_src/mysql | s3cmd put - s3://mysql-backup-demo/mysql_backup_180423.tar.gz

ここでは、tarを使用してMySQLデータディレクトリを圧縮およびアーカイブし、出力をs3cmdにパイプします。これを使用して、圧縮されたアーカイブをSpacesに転送します。 圧縮アーカイブにmysql_backup_180423.tar.gzという名前を付けました。

詳細モードでtarを使用したため、圧縮されているファイルのリストが表示されます(この出力を非表示にするには、上記のコマンドで-vフラグを省略します)。

出力は、次のファイル転送情報で終了します。

Output...
upload: '' -> 's3://mysql-backup-demo/mysql_backup_180423.tar.gz'  [part 1, 1417kB]
 1451996 of 1451996   100% in    0s  1993.41 kB/s  done

転送が完了すると、スペースのコンテンツを一覧表示して、ファイルがスペースに正常に転送されたことを確認します。

s3cmd ls s3://mysql-backup-demo/

バックアップアーカイブファイルが表示されます。

Output2018-04-23 20:39       297   s3://mysql-backup-demo/mysql_backup_180423.tar.gz

この時点で、DigitalOcean Spacesへの物理的なMySQLバックアップが正常に完了しました。

次に、スナップショットボリュームをアンマウントして削除し、使用済みスペースをボリュームグループvg1に復元します。

[[step-5 -—- unmount-and-drop-snapshot-volume]] ==ステップ5—スナップショットボリュームのアンマウントとドロップ

データがバックアップされたので、このチュートリアルの前半で作成したスナップショットボリュームは使用できなくなり、安全に削除できます。

ボリュームをアンマウントするには、次のコマンドを実行します。

sudo umount /backup_src

/backup_srcをスナップショットボリュームのマウントポイントに置き換えます。

スナップショットボリュームを削除できます。 これを行うには、次のコマンドを実行します。

sudo lvremove vg1/mysql_data_snap

ここで、vg1はボリュームグループ名に対応し、mysql_data_snapはスナップショットボリューム名に対応します。

削除の確認を求めるメッセージが表示されます。これにYと応答する必要があります。

次のような出力が表示されるはずです。

Output Logical volume "mysql_data_snap" successfully removed

スナップショットボリュームが正常に削除されました。 これで、MySQLの完全な物理バックアップが完了し、DigitalOcean Spaceにアップロードされました。

復旧シナリオをすばやく実行して、このチュートリアルを終了します。

[[step-6 -—- test-restore-from-physical-backup]] ==ステップ6—物理バックアップからの復元をテストする

以前にSpacesにアップロードした物理バックアップからMySQLデータベースを復元するには、バックアップをデータベースサーバーに転送し、抽出されたファイルを復元されたMySQLデータディレクトリとして使用します。

まず、バックアップをスペースからデータベースサーバー上のユーザーのホームディレクトリに転送します。

s3cmd get s3://mysql-backup-demo/mysql_backup_180423.tar.gz ~/mysql_backup_180423.tar.gz

ファイル転送の出力が表示されるはずです。

Outputdownload: 's3://mysql-backup-demo/mysql_backup_180423.tar.gz' -> '~/mysql_backup_180423.tar.gz'  [1 of 1]
 1451889 of 1451889   100% in    0s    38.49 MB/s  done

物理バックアップファイルからクリーンリストアをテストするため、実行中のデータベースサーバーを停止し、既存のデータディレクトリを削除します。

まず、MySQLサーバーを停止します。

sudo service mysql stop

次に、MySQLデータディレクトリの内容を削除します。

sudo rm -rf /data/*

このチュートリアルでは、デフォルト以外のMySQLデータディレクトリパスは/dataであることを思い出してください。

次に、MySQLデータディレクトリに物理バックアップアーカイブを抽出します。

sudo tar -xzvf ~/mysql_backup_180423.tar.gz -C /data

データファイルが復元されたので、MySQLデータベースを再起動し、回復できるようにします。

sudo service mysql start

最後に、データベースサーバーにログインして、復元が正常に完了したことを確認します。

mysql -u root -p

パスワードを入力すると、MySQLクライアントプロンプトが表示されます。

OutputWelcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.21-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

ここからいくつかのテーブルをスキャンして、データが完全であることを確認できます。

結論

このチュートリアルでは、LVMのスナップショット機能を活用してファイルシステムをフリーズし、実行中のMySQLインスタンスの完全な物理バックアップと復元を実行する方法を示しました。 LVMを使用してMySQLデータを含む1つ以上のストレージボリュームを管理する場合、この機能は本番データベースをバックアップする便利な方法を提供します。

実稼働環境では、この手順は、適切なログ、監視、およびアラートを使用してスクリプト化およびスケジュールするのが理想的です。 さらに、FLUSH TABLES WITH READ LOCKは(どんなに短くても)マスターサーバーではなく、最小限にロードされたレプリカで実行する必要があります。 少し変更するだけで、上記の手順を適用して、マスター物理バックアップからレプリカをすばやくスピンアップすることもできます。

MySQLインスタンスがストレージエンジンとしてInnoDBのみを使用している場合、Percona XtraBackupを使用して、同様の方法でデータベースの物理バックアップを実行することもできます。 詳細については、How To Back Up MySQL Databases to Object Storage with Percona on Ubuntu 16.04に関するチュートリアルを参照してください。

物理バックアップファイルをSpacesにアップロードする合理的な代替手段は、LVMスナップショットをドロップレットスナップショットと組み合わせて使用​​することです。 ドロップレットスナップショットの詳細については、DigitalOcean Backups and Snapshots Explainedを参照してください。

このガイドで使用されているオブジェクトストアであるDigitalOceanSpacesの詳細については、An Introduction To DigitalOcean Spacesを参照してください。