スマートスタイル TECH BLOG

データベース&クラウド技術情報

MySQL Shell 8.0.28新機能 オブジェクトのフィルタリング機能の紹介

はじめに

2022年1月18日にリリースされたMySQL Shell 8.0.28からダンプユーティリティーとダンプロードユーティリティーで、スキーマやテーブル、トリガー、ルーチン、イベントのダンプ及びロードを個々に制御できるようになりました。

MySQL Shell’s instance dump utility util.dumpInstance(), schema dump utility util.dumpSchemas(), table dump utility util.dumpTables(), and dump loading utility util.loadDump() have new filtering options to cover all objects that can be dumped and loaded. The options give you fine control over the content of the dump files and over what objects are loaded onto the destination server, and enable you to skip any objects that are causing issues. At an appropriate level for the utility, the options allow you to include or exclude a specified list of schemas, tables, routines, events, or triggers.

引用元 : Changes in MySQL Shell 8.0.28 (2022-01-18, General Availability)

特定のオブジェクトをフィルタリングする機能はmysqlpumpにもあるため、本記事ではmysqlpumpと比較しながら、MySQL Shellの新機能について確認していきたいと思います。

mysqlpumpの使用方法

mysqlpumpは論理バックアップを実行するクライアントユーティリティーです。

ダンプする際は以下のように任意のファイルに出力します。

インポートする際は、例えば、以下のようにmysqlクライアントでファイルに含まれているステートメントを実行します。

なお、mysqlpumpはデフォルトで全てのスキーマを含めます。
また、–triggers,–routines,–eventsもデフォルトで有効となっています。
そのため、以下のように何もオプションを指定しない場合は、全てのスキーマ、テーブル、イベント、トリガー、ルーチンがダンプされます。

※ただし、INFORMATION_SCHEMAなど一部のオブジェクトはダンプされません。詳しくは下記ドキュメントをご参照ください。
4.5.6 mysqlpump — A Database Backup Program | mysqlpump Restrictions

特定のスキーマ、テーブル、イベント、トリガー、ルーチンをダンプに含める場合は以下のオプションを使用します。

特定のスキーマ、テーブル、イベント、トリガー、ルーチンをダンプに含めない場合は以下のオプションを使用します。

Instance Dump Utility, Schema Dump Utility, 及び Table Dump UtilityとDump Loading Utility

公式リファレンスは以下になります。

MySQLの各ダンプユーティリティを使用する場合、それぞれ以下のようなコマンドを実行します。

インポートする際は、Dump Loading Utilityを使用します。

例えば、util.dumpInstanceを使用する場合、以下のコマンドで/backup1にダンプファイルを作成します。

/backup1には以下のようにファイルが作成されます。

ダンプしたファイルは以下のコマンドでロードすることができます。

特定のスキーマ、テーブル、イベント、トリガー、ルーチンをダンプに含める場合は以下のフィルタリングオプションを使用します。

  • includeSchemas: array of strings
  • includeTables: array of strings
  • includeEvents: array of strings
  • includeRoutines: array of strings
  • includeTriggers: array of strings

特定のスキーマ、テーブル、イベント、トリガー、ルーチンをダンプに含めない場合は以下のオプションを使用します。

  • excludeSchemas: array of strings
  • excludeTables: array of strings
  • excludeEvents: array of strings
  • excludeRoutines: array of strings
  • excludeTriggers: array of strings

なお、MySQL ShellではInstance Dump Utility, Schema Dump Utility及びTable Dump UtilityとDump Loading Utilityの双方で上記のオプションが使用できます。
つまりダンプ時とインポート時のどちらでも、特定のオブジェクトを含めるか否かを選択することができます。

オブジェクトのフィルタリング方法

まずは検証用の環境を準備します。
今回は移行元(DB1)と移行先(DB2)として2つのMySQLを用意しました。
バージョンは以下の通りです。

  • MySQL8.0.28
  • MySQL Shell 8.0.28

次に移行元のMySQLにデータを作成します。
スキーマとテーブルを作成します。

トリガー、イベント、ルーチンを作成します。

test_trigger_1,test_trigger_2d1.t1に、test_trigger_3d1.t3に関連付けられたトリガーとなっています。
また、test_event_1test_procedure_1d1に関連付けられています。

mysqlpump

mysqlpumpで全トリガー中、test_trigger_1のみダンプする場合は以下のコマンドとなります。また、この場合スキーマやテーブル、イベント、ルーチンは全てダンプされます。

また、mysqlpumpではワイルドカードを使用して、含める/含めないオブジェクトを指定することができます。
以下のようにtest_trigger_%とするとこれに一致するトリガーがダンプに含まれます。

なお、トリガーについては、--include-tablesまたは--exclude-tablesオプションを使用すると、そのテーブルに関連付けられているトリガーにも適用されます。
例えば、以下のコマンドの場合d1.t1に関連するトリガーのみがダンプに含まれます。

MySQL Shell

MySQL Shellでtest_trigger_1のみダンプする場合は以下のコマンドとなります。また、スキーマやテーブル、イベント、ルーチンは特に指定していないため、全てダンプされます。

また、MySQL Shellのdump,loadユーティリティーのワイルドカードの使用についてはドキュメントに記載はありません。
実際に以下のようにワイルドカードを使用するとエラーとなりました。

なお、トリガーの場合は、<スキーマ>.<テーブル>.<オブジェクト>と指定するところで、<スキーマ>.<テーブル>と指定した場合、
<スキーマ>.<テーブル>に関連するトリガーを含める/含めないことができます。
例えば、以下のコマンドの場合d1.t1に関連するトリガーが全てダンプに含まれます。

/backup2を確認すると1@t1.triggers.sqlファイルが存在し、その中身にはd1.t1.test_trigger_1d1.t1.test_trigger_2の定義が記載されていることがわかります。

特定のオブジェクトのみをダンプする

mysqlpump

例えば、特定のテーブルのみをダンプしたい場合は次のようなオプションを使用します。
ここでは
–include-databases–include-tablesでスキーマとテーブルを指定し、
–no-create-db–skip-routines–skip-triggers–skip-eventsで各オブジェクトのCREATE文の出力を抑制します。

テーブル定義のみダンプし、データを含めたくない場合は、さらに–skip-dump-rowsを追加します。

特定のトリガーのみダンプしたい場合は、次のようなオプションを使用します。
–no-create-infoCREATE TABLEの出力を抑制し、 –include-triggersでダンプするトリガーを指定します。

イベントやルーチンの場合も –include-events, –include-routines
を使用することで、同じことが可能です。

MySQL Shell

MySQL Shellには以下のようなオプションがあり、DDLのみのダンプかデータのみのダンプかを選択できるようになっています。
デフォルトではどちらもfalseです。

  • ddlOnly: [ true | false ]
    • trueの場合、DDLファイルのみが含まれ、データはダンプされません。
    • デフォルトでfalseです。
  • dataOnly: [ true | false ]
    • trueの場合、データのみが含まれ、DDLはダンプされません。
    • デフォルトでfalseです。

特定のテーブルをダンプしたい場合は、以下のようにオプションを指定します。

また、データはダンプせずにテーブル定義のみをダンプする場合は、以下のようにオプションを指定します。

また、イベント、トリガー、ルーチンに関しては、ダンプに含めるか否かを以下のオプションで制御することができます。すべてデフォルトでtrueです。

  • events: [ true | false ]
  • triggers: [ true | false ]
  • routines: [ true | false ]

しかし、mysqlpumpの--no-create-infoのようなCREATE TABLEを含めない(その他のDDLは含める)といったオプションはありません。

そのため、CREATE DATABASE | TABLEを含めず、特定のCREATE TRIGGER | EVENT | PROCEDUREのみをダンプするといった制御はできないようです。

ただし、イベントとルーチンの場合は以下のように、スキーマのテーブルを全て除外することで、スキーマ、イベント、ルーチンのみのDDLを出力することができました。

一方、トリガーの場合は、関連するテーブルが含まれていないとダンプできないようで、以下のようにテーブルを全て含めないようにして、トリガーを指定するとエラーとなりました。

進行状況について

mysqlpumpでは、–watch-progressオプションで進行状況が表示します。これはデフォルトで有効です。

MySQL Shellでは、showProgressオプションをtrueに指定すると進行状況が表示されます。これもデフォルトでtrueです。

また、MySQL Shellではインポートの際には進行状況が永続的なファイルに保存されます。
これにより、ロードが途中で中断された場合、途中から再開することができるようになっています。

インポートの進行状態は永続的な進行状態ファイルに格納され、正常に完了したステップと中断または失敗したステップが記録されます。 デフォルトでは、進捗状態ファイルは load-progress.server_uuid.json という名前でダンプディレクトリに作成されますが、別の名前と場所を選択することもできます。 ダンプロードユーティリティは、ダンプのインポートを再開または再試行するときに進行状態ファイルを参照し、完了したステップをスキップします。

引用元 : 8.6 ダンプロードユーティリティ

注意が必要なのは、この機能はデフォルトで有効であり、永続的にファイルに記録されるということです。

そのため、一度データをインポートした後に、例えば操作ミスでテーブルを誤って削除してしまった場合などに、再度ファイルをインポートしたい場合に、util.loadDump()を再度実行しても何もインポートされません。
進行状況を記録するファイルには全てのインポートが完了済みと記録されているためです。

試しに、先ほどダンプした/backup6を移行先のDB2にインポートしてみます。

再度、インポートを実行します。実際にはデータのインポートは行われていないため、出力内容が変化していることが確認できます。

次にd1.t1を削除した後に、再度インポートを実行します。

削除されたd1.t1は再度インポートを実行しても、再作成されるわけではないことがわかります。

進捗状態ファイルはprogressFileオプションで指定でき、デフォルトでload-progress.<server_uuid>.json という名前で作成されます。
先ほどutil.loadDump("/backup6")を実行した後には以下のように記録されています。

再度インポートしたい場合は、progressFileで別のファイル名を指定するか、resetProgresstrueに設定します。
resetProgresstrueにすると、進行状態がリセットされ、インポートが最初から再開されます。

なお、ダンプロードユーティリティはデフォルトでは作成済みのオブジェクトを自動でスキップはしないため、再度インポートをする場合は、手動で作成済みのオブジェクトを削除する必要があります。
もしくは、ignoreExistingObjectstrueに設定することで、作成済みのオブジェクトをスキップすることもできます。この場合、作成済みのオブジェクトとダンプファイルのオブジェクトの内容が完全に一致するかまではチェックされないため、注意が必要です。

また、この進行状況の記録はテーブルとスキーマは個々に記録されていますが、トリガーやイベント、ルーチンは個別に記録されていません。
例えば、トリガーが以下のようにテーブル単位での記録となっています。

つまり、d1.t1.test_trigger_1を除きインポートした場合であっても、ファイルにはd1.t1にはd1.t1関連付けられたトリガーのインポートは完了したと記録されます。
再度インポートを実行しても、初回に除外したトリガーがインポートされるという動作にはなりません。

まずは先ほどインポートしたd1スキーマを削除します。
resetProgress: trueで進行状況の記録をリセットし、includeTriggersd1.t1.test_trigger_1のみを指定します。

作成されているトリガーはtest_trigger_1のみです。
一方、ファイルにはd1.t1d1.t3に関連するトリガーについて完了済みと記録されています。

そのため、再度test_trigger_2,test_trigger_3をインポートしようとしても、これらのトリガーは作成されません。

まとめ

オブジェクトをフィルタリングした場合の進行状況の記録のされ方はオブジェクトによって異なるため、フィルタリング機能を使用しつつ、再ロードを実施する場合は、注意する必要がありそうです。

オブジェクトのフィルタリング自体はmysqlpumpですでにできたことですが、MySQL Shellではインポート時にもフィルタリングができるようになり、ますますMySQL Shellの機能が充実してきています。
今後もMySQL Shellのアップデートにも注目していきたいと思います。

Return Top