前書き
定期的なデータベースバックアップは、意図しないデータ損失イベントから保護するための重要なステップです。 効果的なバックアップおよびリカバリ戦略の設計には、多くの場合、パフォーマンスへの影響、実装コスト、およびデータストレージコストとリカバリ速度、データ整合性、およびバックアップカバレッジのトレードオフが伴います。 最適なソリューションは、リカバリポイントと時間objectives、およびデータベースの規模とアーキテクチャによって異なります。
このガイドでは、LVMスナップショットを使用して、実行中のMySQLデータベースのライブ(または「ホット」)物理バックアップを実行する方法を示します。 次に、データを圧縮してDigitalOcean Spaceに保存します。
このチュートリアルで説明する手順は、大規模なMySQLデータベース、ストレージエンジン(InnoDB、TokuDB、MyISAMなど)を混合して使用するデータベース、およびLVMを使用して管理される複数のブロックストレージボリュームを備えたデータベースサーバーに適しています。
Ubuntu 16.04サーバーがLVMスナップショットを取得してマウントできることを確認することから始めます。 次に、MySQLのデータディレクトリを含む論理ボリュームのLVMスナップショットを取得します。 次に、このスナップショットボリューム(凍結した論理ボリューム)をマウントし、MySQLデータディレクトリを圧縮してDigitalOcean Spacesに保存します。 最後に、サンプルの回復シナリオを簡単に説明します。
前提条件
このガイドを使用するには、次の前提条件を満たしている必要があります。
-
Initial Server Setup with Ubuntu 16.04で詳しく説明されているように、sudo権限を持つ非rootユーザーのUbuntu16.04ドロップレット
-
How To Install MySQL on Ubuntu 16.04で詳しく説明されている、実行中のMySQL5.7以降のインストール
-
MySQLデータベースデータディレクトリを格納するために使用されるLVM論理ボリューム:
-
LVMと論理ボリュームのセットアップ方法の詳細については、An Introduction to LVM Concepts, Terminology, and Operationsを参照してください。
-
MySQLのデータディレクトリをデフォルトの
/var/lib/mysql
の場所から移動する方法の詳細については、How To Move a MySQL Data Directory to a New Location on Ubuntu 16.04を参照してください。
-
-
How To Create a DigitalOcean Space and API Key.で詳細に説明されている、DigitalOceanスペースとAPI資格情報のセット
-
Step 1 of How To Use Logrotate and S3cmd to Archive Logs to Object Storage on Ubuntu 16.04で説明されているようにインストールされた
s3cmd
コマンドラインファイル転送クライアント(2.X) -
How To Configure s3cmd 2.x To Manage DigitalOcean Spacesで詳しく説明されているように、スペースにアクセスするように構成された
s3cmd
このすべてを設定したら、このガイドから始める準備ができました。
[[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つあることがわかります(vg1
はmysql_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をクリックします。
このペインから、ドロップレットに接続されているブロックストレージボリュームが表示されます。 このガイドで使用されているUbuntuドロップレットには、ブロックストレージボリュームが1つ添付されています。
Moreをクリックしてから、Resize volumeをクリックします。
ここから、いくつかの定義済みボリュームサイズのいずれかを選択するか、独自のボリュームサイズを選択できます。 500GBのボリュームを100GBから600GBに増やしましょう:
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を参照してください。