スマートスタイル TECH BLOG|データベース&クラウドの最新技術情報を配信

MySQL Enterprise Backup 8.0.20でフルバックアップから特定のテーブルをリストアする

はじめに

MySQL Enterprise Backup(MEB) 8.0.20 以降のバージョンでは、フルバックアップから特定のテーブルをリストアできるようになりました。

For MySQL Enterprise Backup 8.0.20 and later:
Table-Level Recovery (TLR) now allows selective restores of tables or schemas from full backups; see Section 5.1.4, “Table-Level Recovery (TLR)” for details.

引用 :MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: 3 What’s New in MySQL Enterprise Backup 8.0?

マニュアル上では、Table-Level Recovery (TLR) もしくは、partial restore とも表記されています。

これまでのバージョン(~8.0.19)では、予め取得済みの部分バックアップからの部分リストアは可能です。
更に言えば、InnoDBストレージエンジンのテーブルに対しての部分バックアップは、リストア時の煩雑さやエラー発生を極力回避するために、トランスポータブルテーブルスペース機能(TTS)を使用してバックアップ(--include-table='some_table' --use-tts)することがほぼ必須でした。

MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: 4.3.5 Making a Partial Backup

しかしながら、このTTSバックアップは制約事項が多いため、結果的に採用を見送ることになる、ということも想像に難くありません。

※具体的な制約事項はマニュアルの以下のページでご確認ください。
MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: 19.8 Partial Backup and Restore Options
MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: B Limitations of MySQL Enterprise Backup

また、フルバックアップで取得しているのに、特定のテーブルのみ重複して個別でバックアップを取っておかなければならないという点も効率があまりよくありません。

一方、フルバックアップからどうにかしてある特定のテーブルのみをリストアしたい場合どのような手法があるかというと…

  • リカバリ対象のMySQLとは別のインスタンス、およびフルバックアップをリストア可能なディスクスペースを別途用意
  • そこへフルリストア後、mysqldumpなどで対象テーブルのデータを抽出

という間接的でコストが掛かる方法ぐらいしかありませんでした。


本記事では、部分リストアがよりシンプルに実現できるようになったTable-Level Recovery (TLR)を確認してみたいと思います。

要件と制約を確認してみる

マニュアルに記載されている、部分リストアを使用するための要件と、使用上の制約や注意事項を(ほぼ素文直訳ですが)要約してみました。

MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: 5.1.4 Table-Level Recovery (TLR)

要件

  • リストア先サーバーが実行中であること
  • リストア先サーバーとバックアップ作成サーバーのページサイズが同じであること
    ※これは通常は同一サーバー・インスタンスでバックアップするのですが、バックアップを別サーバーでリストアしたい場合の要件になると思います。
  • リストア先サーバーで innodb_file_per_table オプションを有効にする
  • 非TTSバックアップの場合、リストアするテーブルは、リストア先サーバー内に同じテーブル定義で既に存在していること
  • TTSバックアップの場合、リストアするテーブルは、リストア先サーバー内に存在していないこと
  • リストア時に --datadir オプションは必須ではないが、付与する場合はリストア先サーバーに合わせないとリストアに失敗する

大前提としては、通常のフルバックアップからのリストアと異なり、オンラインで行われる必要があります
そして、MySQL5.6以降デフォルトとして定着している innodb_file_per_table の機能を用いて行われるため、こちらも必須です。

『非TTSバックアップの場合、リストアするテーブルは、リストア先サーバー内に同じテーブル定義で既に存在していること』というのは、実際にリストアしようとしたときに引っかかりそうです。
DROP TABLE してしまったり、ALTER TABLE でテーブル定義を変更してしまったというインシデントを元に戻そうとするには、まずバックアップ時点と同じテーブル定義でテーブルを作成しておかなくてはいけない、ということになります。

本機能を導入するのであれば、日ごろからDB内のテーブル定義を構成管理しておくとともに、MEBによる物理バックアップ以外にmysqldump --no-dataなどを使用して、最新のテーブル定義情報もバックアップしておくことをお勧め致します。

制限

  • 個別のパーティションを指定して復元できない。パーティションテーブルは全体がリストアされる
  • 増分バックアップでは実現できない
  • バイナリログ、リレーログ、UNDOログはリストアされない
  • 非TTSバックアップの場合の追加制限事項
    • 部分的な復元の後、コミットされていないトランザクションからの変更がテーブルに含まれる可能性がある。
    • TLRで復元されたテーブルの自動インクリメント値は、バックアッププロセスの最後の値と同じでない場合がある。
    • 暗号化されたInnoDBテーブルを部分リストアに含めることはできない。

パーティションテーブルにおいて、個別のパーティション単位で指定してリストアできない、というのは以前からのTTSバックアップからの部分リストアでも同じです。
この点、パーティションテーブルの性質上、非常にニーズがあると思いますので、現時点でTLRの対象外ということは残念ではありますが、今後の機能拡張に期待したいです。

増分バックアップではTLRは使用できない旨、明記されているのですが、この点は新たな発見があったので後述説明したいと思います。

非TTSバックアップの場合の追加制限事項として2点ほど注意書きがあり、ユーザー視点では非常に気になる内容ですが、いずれも発生条件は明記されておりません。

暗号化されたInnoDBテーブルに関しては、バージョン8.0.20 までは上記の通りですが、8.0.21のアップデートで、TTSを使用した部分バックアップ・リストアに含められるようになりました。
(注意としては、本記事で取り上げているフルバックアップからの部分リストアには まだ対応していない、ということになります)

For MySQL Enterprise Backup 8.0.21 and later:
Encrypted InnoDB tables can now be included in partial backups and restores using transportable tablespaces (TTS).

引用元 :MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: 3 What’s New in MySQL Enterprise Backup 8.0?

フルバックアップからの Table-Level Recovery (TLR) を試してみる

記事タイトルでは8.0.20としていますが、今回は、MySQL・MEB共に、本稿の執筆時最新GAリリースバージョン8.0.21を使用して動作を確認してみました。

なお、8.0.20で試す場合はフルバックアップ実行コマンドの以下の点が異なりますのでご注意ください。

  • --backup-image で指定したmbiファイルがカレントディレクトリに作成されてしまうので、絶対パスを指定するようにしてください。
  • --compress オプションを指定した場合は、TLRを実行時のコマンドには --uncompress オプションを指定するようにしてください。

また、以降の手順に記載しているバックアップのディレクトリパス・ファイル名・ログイン認証情報などは検証用に用意した環境固有の設定ですので、適宜読み替えてください。

非TTSバックアップ(通常のバックアップ)からTLR

db1スキーマにテスト用のtbl1テーブルを作成し、適当なデータをInsert後、MEBでフルバックアップを取得しました。

tbl1のデータを TRUNCATE TABLE してしまいます。

ここでTLRの出番です。

この環境ではrootユーザーでMEBを実行していましたので、フルバックアップはすべてrootユーザー所有になっています。オンラインでリストアするため、ファイルオーナーとパーミッションの関係でリストアが失敗しないように、オーナーをmysqlユーザーに変更しておきます。

今回のフルバックアップは単一イメージファイル形式で取得していたので、そのリストアの際にメタデータファイルなどを一時的に展開するディレクトリを指定する必要があり、事前に準備しておきます。(空ディレクトリである必要があります)

TLRを実行します。
※rootユーザーで実行すると、バックアップファイルをコピーバックする際にディレクトリとファイルのオーナがrootユーザー所有になってしまい、リストアが失敗してしまいますので、以下コマンドの通りにmysqlユーザーとしてリストアを実行してください。

マニュアルに記載の通り--include-tables オプションにはPOSIX 1003.2標準の正規表現構文が使えます。

また、--exclude-tables オプションで除外対象のテーブルの指定も組み合わせることができます。

実行ログの出力を、TLRにフォーカスして抜粋しました。
非TTSバックアップからのリストアである旨のメッセージが確認できます。

ログメッセージで気づいたのですが、TDE(暗号化InnoDBテーブル)だけでなく、一般テーブルスペース内に作成されたテーブルもこの機能では対象外になるというメッセージが出力されています。
※一般テーブルスペースについてはリファレンスマニュアルをご参照ください。
MySQL :: MySQL 8.0 Reference Manual :: 15.6.3.3 General Tablespaces

TLR完了後、期待通り対象テーブルがバックアップ時のデータでリカバリされました。

なお、TRUNCATE TABLE ではなく DROP TABLE した状態でTLRを実行してみたところ、制約事項に記載されている通りの挙動となり、以下のエラーが発生して処理が中断されました。

非TTSバックアップの場合の追加制限事項に書かれている現象が発生するか

前述の通り非常に気になる制約が記載されているので、実際に起こり得るのか確かめたかったのですが…

残念ながらいずれも複数回TLRを実行してみたところでは、以下の事象は発生しませんでした。

  • 非TTSバックアップの場合の追加制限事項
    • 部分的な復元の後、コミットされていないトランザクションからの変更がテーブルに含まれる可能性がある。
    • TLRで復元されたテーブルの自動インクリメント値は、バックアッププロセスの最後の値と同じでない場合がある。

他トランザクションが対象テーブルを更新中かつ未コミットの状況でMEBがTLRを行った場合、当然ロックがかかっていますので、コミットorロールバックされるまで以下の処理が待たされていることは確認しました。

今回の検証では未解明となり、心残りではありますが、もしこの事象に遭遇する、または発生条件などを具体的に知りたい場合はOracleサポートへお問い合わせいただくようお願い致します。

増分バックアップを適用したフルバックアップからTLR

制約事項には増分バックアップでは実現できないと明記されていますので、増分or差分バックアップ計画で運用中のDBには利用できないものと読み取れます。

しかし、今回動作を確認してみたところ、厳密に言えば、 増分バックアップをリストア適用したディレクトリフルバックアップからはTLRを実行することが出来ました。

当然のことながら、増分バックアップは変更分のみを含んでいるのでベースのフルバックアップがあってこそのバックアップファイルであり、それ自体から特定のテーブルデータを丸々抽出する、というのは不可能なので、マニュアルの制約事項の通りではあります。

かつ、単一イメージ形式で取得した増分バックアップをリストア適用するには、まず最初にフルバックアップを対象のMySQL上でリストアした後に、そこに対して増分バックアップをcopy-back-and-apply-logしていかなくては実現しません。

There are different ways to use incremental backups to restore a database under different scenarios. The preferred method is to first restore the full backup and make it up-to-date to the time at which the full backup was performed using the copy-back-and-apply-log command (see Example 5.1, “Restoring a Database” on how to do it), then use copy-back-and-apply-log again to restore the incremental backup image on top of the full backup that was just restored:

引用元 :MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: 5.1.3 Restoring an Incremental Backup :: Advanced: Restoring an Incremental Backup Directory

ところが、ディレクトリフルバックアップの場合は、対象のMySQLにリストアをせずともバックアップディレクトリに対して増分バックアップを適用できるという仕組みがあります。

Incremental directory backups can be restored in a series of copy-back-and-apply-log command, as illustrated above for single-file backups. Alternatively, at anytime after an incremental backup is taken and before the data is restored, you can bring your full backup up-to-date with your incremental backup. First, apply to the full backup any changes that occurred while the backup was running:

引用元 :MySQL :: MySQL Enterprise Backup 8.0 User’s Guide :: 5.1.3 Restoring an Incremental Backup

これを利用して、ディレクトリバックアップ内で増分を適用させ最新の状態にしたフルバックアップからTLRが行うことが出来ました。

運用上、単一イメージバックアップ形式で取得する必要がある場合はこの方法は採用するのが難しいかもしれませんが、そうでない場合は制約ではなくなることになります。

まとめ

データベースの利用(運用)上、システムによっては「オペレーションミスなどが発生してしまったので特定のテーブルデータをバックアップ時点まで戻したい」という状況・局面は少なからず発生するものかと思います。
そうならないようなシステム作りや運用設計にすることが理想論ではあるものの、どうしても回避できない・防げない、という実状もあるかもしれません。

MySQLのバージョンアップと併せてMEBのバージョンも上げることで、不慮の事故に対するリカバリのためにフルバックアップから抽出できるようになり、対応の柔軟性向上が見込めるのではと思います。

意外といままで出来そうで出来なかった機能として、非常に有益なアップデートだと感じました。

諸々の制約事項があり、もちろん対応できないリカバリケースもあると思いますので、実運用に導入する際にはしっかりとリカバリテストを重ねていただくことを推奨いたしますが、是非 MEB 8.0.20以降で試していただきたいです。


MySQL

 

Return Top