LVMスナップショットを使用してMySQLデータベースをDigitalOceanスペースにバックアップする方法
序章
定期的なデータベースのバックアップは、意図しないデータ損失イベントを防ぐための重要なステップです。 効果的なバックアップおよびリカバリ戦略の設計には、多くの場合、パフォーマンスへの影響、実装コスト、およびデータストレージコストと、リカバリ速度、データ整合性、およびバックアップカバレッジとのトレードオフが含まれます。 最適なソリューションは、リカバリポイントと時間目的およびデータベースの規模とアーキテクチャによって異なります。
このガイドでは、LVMスナップショットを使用して実行中のMySQLデータベースのライブ(または「ホット」)物理バックアップを実行する方法を示します。 次に、データを圧縮してDigitalOceanSpaceに保存します。
このチュートリアルで紹介する手順は、大規模なMySQLデータベース、ストレージエンジン(InnoDB、TokuDB、MyISAMなど)を組み合わせて使用するデータベース、およびLVMを使用して管理される複数のブロックストレージボリュームが接続されたデータベースサーバーに適しています。
まず、Ubuntu16.04サーバーがLVMスナップショットを取得してマウントできることを確認します。 次に、MySQLのデータディレクトリを含む論理ボリュームのLVMスナップショットを作成します。 次に、このスナップショットボリューム(凍結された論理ボリューム)をマウントし、MySQLデータディレクトリを圧縮してDigitalOceanSpacesに送信して保存します。 結論として、サンプルのリカバリシナリオについて簡単に説明します。
前提条件
このガイドを使用するには、次の前提条件を利用できる必要があります。
- Ubuntu 16.04を使用したサーバーの初期設定で詳しく説明されている、sudo権限を持つ非rootユーザーのUbuntu16.04ドロップレット
- Ubuntu 16.04にMySQLをインストールする方法で詳しく説明されている、実行中のMySQL5.7以降のインストール
- MySQLデータベースのデータディレクトリを保存するために使用されるLVM論理ボリューム:
- LVMの詳細と論理ボリュームのセットアップ方法については、 LVMの概念、用語、および操作の概要を参照してください。
- MySQLのデータディレクトリをデフォルトの
/var/lib/mysql
の場所から移動する方法の詳細については、MySQLデータディレクトリをUbuntu16.04の新しい場所に移動する方法を参照してください。
- DigitalOceanスペースとAPIキーの作成方法で詳しく説明されているDigitalOceanスペースとAPIクレデンシャルのセット
s3cmd
コマンドラインファイル転送クライアント(2.X)は、LogrotateおよびS3cmdを使用してUbuntu16.04のオブジェクトストレージにログをアーカイブする方法のステップ1で詳しく説明されています。- DigitalOceanスペースを管理するためのs3cmd2.xの構成方法で詳しく説明されているように、スペースにアクセスするように構成された
s3cmd
これらすべてを設定したら、このガイドを開始する準備が整います。
ステップ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の構成によって異なることに注意してください。 このガイドで使用されているUbuntu16.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およびFreePE / Size の行から、vg1
ボリュームグループに475GBが割り当てられ、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サイズから、/dev/vg1/mysql_data
にある475GBの論理ボリュームmysql_data
が1つあることがわかります(vg1
はmysql_data
のボリュームグループ)。
要約すると、このチュートリアルで使用したUbuntu 16.04サーバーには、1つのボリュームグループ(vg1
)をバックアップするために使用される1つの500GB物理ボリューム(/dev/sda
)があり、そこから1つのボリュームを作成しました。 475GB論理ボリューム(mysql_data
)。 これにより、ボリュームグループに25GBの空き領域が残り、これを使用してさらに論理ボリューム(およびスナップショット)を作成できます。
ハードウェアとLVMの構成は異なる可能性があります。 複数のブロックストレージデバイスが接続され、単一または複数のボリュームグループにプールされている場合があります。 それでも、特定の論理ボリュームのスナップショットを作成する手順は同じです。
このセクションに示されている一連のコマンドを使用すると、LVMとハードウェア構成の概要を理解できるはずです。
次のステップでは、LVMスナップショット用にデータベースサーバーを準備します。
ステップ2—LVMスナップショット用にサーバーを準備する
LVMスナップショットを安全に取得できるようにするには、バックアップおよびSpacesへのファイル転送中に発生する可能性のある書き込みまたは変更をカバーするのに十分なディスクスペースをプロビジョニングする必要があります。 データベースのサイズによっては、このバックアップが完了するまでに数時間かかる場合があるため、ここでは注意を怠るのが最善です。 バックアップの実行中にスナップショットボリュームの容量が不足すると、スナップショットボリュームが無効になり、一貫性のあるバックアップができなくなります。
前のステップで、プリンシパル論理ボリューム(mysql_data
)を含むボリュームグループ(vg1
)の空き容量が25GBしかないことを確認しました。 データベースのバックアップにかかる時間内に25GBの変更がディスクに書き込まれない場合もありますが、理想的には少なくとも100GBの安全マージンが必要です。 本番環境では、スケジュールされたバックアップウィンドウ中にディスクに書き込まれるデータの平均量を測定し、それに応じてスナップショットボリュームサイズをスケーリングすることがベストプラクティスになります。
vg1
ボリュームグループに75GBのスペースを追加するには、ブロックストレージデバイスを接続するか、現在ドロップレットに接続されているボリュームのサイズを大きくします。 このチュートリアルでは、すでに接続されているブロックストレージボリュームを拡張します。 追加のブロックストレージボリュームの接続の詳細については、 DigitalOceanBlockStorageの概要を参照してください。
注:一部のリージョンはまだブロックストレージをサポートしておらず、ブロックストレージボリュームをドロップレットに接続できない場合があります。 この場合の合理的な回避策は、ドロップレットのスナップショットを作成し、このスナップショットイメージを使用して新しいドロップレットを作成し、それにブロックストレージを追加することです。
このドロップレットに添付されているブロックストレージボリュームを拡張してみましょう。
DigitalOceanのWebコントロールパネルに移動し、ダッシュボードからドロップレットに移動します。
サイドバーで、ボリュームをクリックします。
このペインから、ドロップレットに接続されているブロックストレージボリュームが表示されます。 このガイドで使用されているUbuntuドロップレットには、1つのブロックストレージボリュームが接続されています。
その他をクリックしてから、ボリュームのサイズ変更をクリックします。
ここから、いくつかの事前定義されたボリュームサイズのいずれかを選択するか、独自のボリュームサイズを選択できます。 500GBのボリュームを100GBから600GBに増やしましょう。
続行を押します。 これで、接続されたブロックのストレージボリュームが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 ]
ボリュームグループの空き容量も100GB増加したことを確認しましょう。
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で十分ですが、実稼働環境では、バックアップウィンドウで予想されるディスク使用量に比例してスナップショットのボリュームサイズをスケーリングする必要があります。
ボリュームグループに、スナップショットとバックアップ中に発生する可能性のある書き込みや変更をカバーするのに十分なスペースができたので、スナップショットボリュームの作成に進むことができます。
ステップ3—LVMスナップショットを作成してマウントする
警告: LVMスナップショットがアクティブな間は、ディスクへの書き込み時にパフォーマンスが低下します。 最初に、シミュレートされた負荷のある非本番データベースを使用してこの手順をテストし、この方法が本番デプロイメントで機能することを確認する必要があります。
次に、lvcreate
を使用して、mysql_data
論理ボリュームのスナップショットを作成します。 これを行う前に、データの一貫性を保証できるように、FLUSH TABLES WITH READ LOCK
を使用してデータベースへの書き込みをフリーズする必要があります。 テーブルは、lvcreate
を実行するまで読み取りロックする必要があります。実行すると、ロックを解除できます。 この一連のコマンドをスクリプト化する場合、現在実行中の書き込みクエリに応じて、合計ロック時間は非常に短くなります。
ロックMySQLデータベースを読む
テーブルをフラッシュすることから始めましょう。 データベースサーバーのターミナルから、mysql
を使用してMySQLデータベースにログインします。
mysql -u root -p
MySQLシェルから、FLUSH TABLES
コマンドを実行して、データベースを読み取りロックします。
警告:次のコマンドを実行すると、開いているすべてのテーブルが閉じられ、すべてのデータベースのすべてのテーブルがグローバル読み取りロックでロックされます。 これを本番データベースで実行する場合は、このコマンドをレプリカで実行するか、スクリプトの一部として実行して、データベースがロックされる時間を最小限に抑えることをお勧めします。
FLUSH TABLES WITH READ LOCK;
次の出力が表示されます。
OutputQuery OK, 0 rows affected (0.00 sec)
これは、データベースがリードロックされていることを示しています。 MySQLプロンプトを終了しないでください。開いたままにしておく必要があります。
次に、MySQLデータを格納するために使用される論理ボリュームのLVMスナップショットを作成してマウントします。
- スナップショットボリュームの作成とマウント
このMySQLクライアント接続を開いたまま、新しいターミナルウィンドウからデータベースサーバーにログインします。
警告:この接続を閉じると、ロックが破棄されて書き込みが再開され、スナップショットの一貫性が失われます。
これで、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
データの一貫したスナップショットにアクセスできるようになったので、データをDigitalOceanSpaceにバックアップできます。
ステップ4—ファイルを圧縮してDigitalOceanSpacesにアップロードする
このバックアップをDigitalOceanSpaceにアップロードするには、前提条件の手順でインストールおよび構成した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: '<stdin>' -> '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
この時点で、DigitalOceanSpacesへのMySQLの物理バックアップが正常に完了しました。
次に、スナップショットボリュームをアンマウントして削除し、使用済みスペースをボリュームグループvg1
に復元します。
ステップ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の完全な物理バックアップが完了し、DigitalOceanSpaceにアップロードされました。
回復シナリオをすばやく実行して、このチュートリアルを終了します。
ステップ6—物理バックアップからの復元をテストする
以前にSpacesにアップロードした物理バックアップからMySQLデータベースを復元するには、バックアップをデータベースサーバーに転送し、抽出したファイルを復元したMySQLデータディレクトリとして使用します。
まず、バックアップをSpaceからデータベースサーバー上のユーザーのホームディレクトリに戻しましょう。
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を使用して、同様の方法でデータベースの物理バックアップを実行することもできます。 詳細については、 Ubuntu16.04でPerconaを使用してMySQLデータベースをオブジェクトストレージにバックアップする方法に関するチュートリアルを参照してください。
Spacesに物理バックアップファイルをアップロードする代わりの合理的な方法は、LVMスナップショットをドロップレットスナップショットと組み合わせて使用することです。 ドロップレットスナップショットの詳細については、DigitalOceanバックアップとスナップショットの説明を参照してください。
このガイドで使用されているオブジェクトストアであるDigitalOceanSpacesの詳細については、DigitalOceanSpacesの概要を参照してください。