スマートスタイル TECH BLOG

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

【MySQL Shell 8.3.0】ダンプ・ロードユーティリティのchecksumオプションについて

MySQL Shell 8.3.0 では、ダンプ・ロードユーティリティでデータのチェックサムを取得し正しくデータがインポートされた事を検証するための機能が実装されました。

https://dev.mysql.com/doc/relnotes/mysql-shell/8.3/en/news-8-3-0.html

It is now possible to generate a checksum for a dump to enable you to validate your data on import. The option checksum: [true | false] is added to the following utilities:

util.dumpInstance(), util.dumpSchemas(), and util.dumpTables(): a metadata file, @.checksums.json is generated containing the details of the dumped data and a checksum for each.

util.loadDump(): validates the checksums after the data is loaded.

util.copyInstance(), util.copySchemas(), and util.copyTables(): generate the metadata file, @.checksums.json, and validate the data.

(WL #15947)

地味ながら、これまで待ち望まれていた機能ではないかと思いますので、今回検証したいと思います。

CHECKSUM TABLEコマンドについて

MySQLではこれまでも テーブルデータが同じであるかを確認するためのコマンドとして CHECKSUM TABLE コマンドがありました。

上記のようにテーブル全体のチェックサムを取得することができますが、テーブルのROW_FORMATの違いや、バージョン間による列データ型の内部的な違いなども差分と含まれてしまうということがあり、
純粋にテーブルに含まれるデータを比較したい、アップグレード前後で値を比較したい、といったニーズでは使うことができませんでした。

MySQL Shellのダンプ・ロードユーティリティにおけるチェックサム検証機能はよりデータのみに特化してチェックサムを取得することが可能です。

ダンプ・ロードユーティリティを使用したデータ移行

アップグレードの際には、サービス停止期間を設けられるようであれば論理バックアップを使用してさっと済ませたいものです。
そのような時にMySQLShellのダンプ・ロードユーティリティは高速にエクスポート・インポートが可能で、論理バックアップのためバージョン間の影響も物理バックアップよりは少ないです。
例えば、以下のように、システムスキーマ(mysql) を除いた形であれば 5.6から一足飛びに 8.0へインポートすることも可能です。

なんだか恐ろしげなWARNINGが発生していますね。

このような場合も、インポート前後でデータのチェックサムを取得できていれば、WARNINGの内容はともかくとしてデータはダンプ・ロード前後のバージョンで一貫していることが担保できるかと思います。

チェックサムの取得方法

ダンプユーティリティ(dumpInstance, dumpSchemas等)のchecksumオプションは以下になります。

https://dev.mysql.com/doc/mysql-shell/8.3/en/mysql-shell-utilities-dump-instance-schema.html

checksum: [ true | false ] If enabled, a metadata file, @.checksums.json is generated with the dump. This file contains the checksum data for the dump, enabling data verification when loading the dump. See Options for Load Control.

The following conditions apply if checksum: true:

If ddlOnly:false and chunking:true, a checksum is generated for each dumped table and partition chunk.

If ddlOnly:false and chunking:false, a checksum is generated for each dumped table and table partition.

If ddlOnly:true, a checksum is generated for each dumped table and table partition.

ロードユーティリティ(loadDump) のchecksumオプションは以下です。

https://dev.mysql.com/doc/mysql-shell/8.3/en/mysql-shell-utilities-load-dump.html

checksum: [true|false] If enabled, the loadDump utility checks the checksum data generated by the dump utility after the corresponding data is loaded. The verification is limited to data which was dumped, ignoring generated data such as invisible primary keys added by the loadDump utility.

Errors are returned if a checksum does not match or if a table is missing and cannot be verified.

If checksum: true but no data was loaded, either due to loadData: false or no data being dumped, the utility verifies the dump’s checksum information against the current contents of the affected tables.

If a table does not exist, an error is displayed for each missing table.

If checksum: true and dryRun: true, the checksum is not verified. A message is displayed stating that no verification took place.

チェックサムを比較するには、ダンプユーティリティ実行時に checksumオプションを有効化しておく必要があります。

チェックサムの取得は --threads に指定したスレッドが各々行うようです。

実際に取得されたチェックサムはダンプディレクトリ配下の @.checksums.json に出力されています。

では、チェックサム付きのダンプデータをインポートします。
この際にも --checksum オプションを付ける必要があります。

Verifying checksum information - done という出力からなんとなくデータ整合性が取れているように見えますが、わざと異なるデータに変更してみましょう。

インポートしたsakilaデータベースを一旦削除して再実行します。

しっかり checksum 処理が失敗していることが確認できました。
行まで特定できればより良いですが、Checksumはチャンク単位のようですので、具体的に何が違うのかはユーザが boundary: (actor_id BETWEEN 1 AND 200) の条件を指定して調査していく必要があります。
チャンクまで特定できればかなり調査は楽になるでしょう。

チェックサム機能を有効化した際のパフォーマンスについて

チェックサム機能を有効化した際のパフォーマンスについて、 TPC-H のデータを使用して確認します。
今回のテストデータは 13G 程度としました。

テスト環境のスペックは以下の通りで、KVMの仮想マシンに CPU 4core/Mem 8GiB を割り当てたものです。

checksum無しでの util.dumpSchema() はダンプに3分38秒かかりました。

checksum=true の場合でもある程度並行して dumpと checksumが実行されるようですが、Totalの時間として2倍程度かかっています。

checksum無しでの util.loadDump() によるインポートには14分42秒かかりました。

checksumありの util.loadDump() によるインポートには21分43秒かかり、内checksumには7分57秒かかっていました。

util.dumpSchema()のチェックサムフェーズでは、以下のクエリが実行されていました。
すべてのカラムをbinary型にキャストしてから比較を行うため、文字コード等の影響は無さそうです。

今回lineitemにはPKを作成していなかったためWHERE条件がついていませんが、PKやUKのあるテーブルではWHERE条件によってチャンクごとに評価されるはずです。

また、チャンク分割されることで --threads で指定したスレッド数をフルに活かした並列処理ができますので、PKの無い(かつ行数の多い)テーブルは無くしておいたほうがパフォーマンス上のメリットがあるでしょう。

注意点としてschemaオプションで別スキーマにインポートするとチェックサムの比較ができずにエラーになるようです

以上が検証結果になります。

移行前後のデータが整合性が取れている、ということを自信を持って言うために、今後のアップグレードやデータ移行時に活用してみてはいかがでしょうか。

Return Top