Dumplingを使ってTiDBのデータをエクスポートしてみた

2024.02.02

Dumplingを使ってTiDBのデータをエクスポートしてみた

CX事業本部@大阪の岩田です。

前回のブログでCSVファイルをTiDBにインポートしてみました。

今度は逆にTiDBからデータをエクスポートする操作を試してみます。

Dumpling

TiDBからのデータエクスポートはDumplingというツールを利用します。DumplingはTiDBだけでなくMySQLにも対応しているので、MySQLのデータをDumplingでエクスポート後にTiDB LightningでTiDBにインポートするといった使い方もできます。Dumplingは様々な機能を持っていますが、公式ドキュメントではDumplingの特徴として以下の点が紹介されています。

Dumplingには以下のようなメリットがあります。

  • SQL や CSV などの複数の形式でのデータのエクスポートをサポートします。
  • データのフィルタリングを容易にするテーブルフィルター機能をサポートします。
  • Amazon S3 クラウドstorageへのデータのエクスポートをサポートします。
  • TiDB に対してさらに最適化が行われています。

Dumpling Overview | PingCAP Docs

環境

今回検証に利用した環境は以下の通りです。

  • TiDB: 5.7.28-TiDB-v6.6.0-serverless
  • Dumpling: v7.6.0

Dumplingの実行はAWSのCloudShell/Google CloudのCloud Shell上から実施しました

やってみる

ここからは公式ドキュメントの手順に従いながら、いくつかのパターンでデータのエクスポートを試していきます

Dumplingのインストール

まずDumplingをインストールします。Dumplingはtiupでインストールできるのでtiup install dumplingを実行してインストールしましょう。

$ tiup install dumpling
download https://tiup-mirrors.pingcap.com/dumpling-v7.6.0-linux-amd64.tar.gz 48.22 MiB / 48.22 MiB 100.00% 5.32 GiB/s

インストールできたらtiup dumpling --versionでバージョン情報でも確認してみましょう。

以下のように出力されればOKです。

Checking updates for component dumpling... Timedout (after 2s)
Starting component dumpling: /home/cloudshell-user/.tiup/components/dumpling/v7.6.0/dumpling --version
Release version: v7.6.0
Git commit hash: 52794d985ba6325d75a714d4eaa0838d59425eb6
Git branch:      heads/refs/tags/v7.6.0
Build timestamp: 2024-01-22 02:14:07Z
Go version:      go version go1.21.5 linux/amd64

SQLファイルにエクスポートしてみる

まずはSQL形式でTiDBの中身をエクスポートしてみましょう。CloudShellから以下のコマンドを実行します。

$ tiup dumpling -u <ユーザー名> -P 4000 -h <TiDB Serverlessのエンドポイント> --filetype sql -t 8 -o /tmp/test -r 200000 -F 4MiB -p <パスワード>

各オプションの意味は以下の通りです

  • -u: ユーザー名
  • -P: ポート番号
  • -h: ホスト名
  • --filetype: エクスポートされるファイルの種類 (csv/sql)
  • -t: 同時バックアップスレッドの数
  • -o: データエクスポート先のパス ローカルファイルシステムだけでなくS3も指定可能
  • -r: テーブル内の同時実行を有効/無効化
  • -F: このオプションで指定したサイズに合わせてエクスポート時にファイルを分割 今回の例だと4MごとにSQLファイルが生成される
  • -p パスワード mysqlコマンドだと-pのみ指定した場合はプロンプトでパスワードが聞かれるのですが、dumplingはコマンドライン引数でパスワードを指定するのが必須のようです。historyに残るので注意が必要ですね

コマンド実行後は以下のように出力されます

[2024/02/02 04:32:19.026 +00:00] [INFO] [versions.go:54] ["Welcome to dumpling"] ["Release Version"=v7.6.0] ["Git Commit Hash"=52794d985ba6325d75a714d4eaa0838d59425eb6] ["Git Branch"=heads/refs/tags/v7.6.0] ["Build timestamp"="2024-01-22 02:14:07"] ["Go Version"="go version go1.21.5 linux/amd64"]
[2024/02/02 04:32:19.472 +00:00] [INFO] [version.go:434] ["detect server version"] [type=TiDB] [version=6.6.0-serverless]
[2024/02/02 04:32:19.478 +00:00] [INFO] [dump.go:1446] ["meet some problem while fetching pd addrs. This won't affect dump process"] [error="sql: SELECT * FROM information_schema.cluster_info where type = 'pd';: Error 1142 (42000): SELECT command denied to user '<ユーザー名>'@'%' for table 'cluster_info', see https://docs.pingcap.com/tidbcloud/limited-sql-features#system-tables for more details."]
[2024/02/02 04:32:19.484 +00:00] [WARN] [dump.go:1506] ["If the amount of data to dump is large, criteria: (data more than 60GB or dumped time more than 10 minutes)\nyou'd better adjust the tikv_gc_life_time to avoid export failure due to TiDB GC during the dump process.\nBefore dumping: run sql `update mysql.tidb set VARIABLE_VALUE = '720h' where VARIABLE_NAME = 'tikv_gc_life_time';` in tidb.\nAfter dumping: run sql `update mysql.tidb set VARIABLE_VALUE = '10m' where VARIABLE_NAME = 'tikv_gc_life_time';` in tidb.\n"]
...略

[2024/02/02 04:32:20.329 +00:00] [INFO] [writer.go:272] ["no data written in table chunk"] [database=fortune500] [table=fortune500_2018_2022] [chunkIdx=0]
[2024/02/02 04:32:20.367 +00:00] [INFO] [writer.go:272] ["no data written in table chunk"] [database=lightning_task_info] [table=conflict_records] [chunkIdx=0]
[2024/02/02 04:32:20.369 +00:00] [INFO] [writer.go:272] ["no data written in table chunk"] [database=lightning_task_info] [table=conflict_records] [chunkIdx=1]
[2024/02/02 04:32:20.402 +00:00] [INFO] [writer.go:272] ["no data written in table chunk"] [database=blog] [table=part] [chunkIdx=0]
[2024/02/02 04:32:20.509 +00:00] [INFO] [collector.go:264] ["backup success summary"] [total-ranges=12] [ranges-succeed=12] [ranges-failed=0] [total-take=241.031795ms] [total-rows=52499] [total-kv-size=5.251MB] [average-speed=21.79MB/s]
[2024/02/02 04:32:20.510 +00:00] [INFO] [main.go:82] ["dump data successfully, dumpling will exit now"]

出力されたファイルを確認してみましょう。

$ tree -h /tmp/test/
/tmp/test/
├── [ 4.0M]  blog.part.0000000010000.sql
├── [ 836K]  blog.part.0000000010001.sql
├── [  453]  blog.part-schema.sql
├── [  132]  blog-schema-create.sql
├── [ 196K]  fortune500.fortune500_2018_2022.0000000010000.sql
├── [  761]  fortune500.fortune500_2018_2022-schema.sql
├── [  138]  fortune500-schema-create.sql
├── [  578]  lightning_task_info.conflict_records-schema.sql
├── [  147]  lightning_task_info-schema-create.sql
└── [  146]  metadata

<DB名>.<テーブル名>.<連番>.sqlという形式で-Fオプションで指定した単位毎にデータがエクスポートされていることが分かります。CREATE TABLE文のようなスキーマ情報は<DB名>.<テーブル名>-schema.sqlという形式で出力されています。

エクスポートされたデータの中身を軽く確認しておきましょう。

$ head /tmp/test/blog.part.0000000010000.sql 
/*!40014 SET FOREIGN_KEY_CHECKS=0*/;
/*!40101 SET NAMES binary*/;
INSERT INTO `part` VALUES
(15,'NUL next','\0','MFGR#47','MFGR#3438','indigo','LARGE ANODIZED BRASS',45,'LG CASE'),
(22,'floral beige','MFGR#4','MFGR#44','MFGR#4421','medium','PROMO, POLISHED BRASS',19,'LG DRUM'),
(23,'bisque slate','MFGR#4','MFGR#41','MFGR#4137','firebrick','MEDIUM \"BURNISHED\" TIN',42,'JUMBO JAR'),
(24,'dim white','MFGR#4','MFGR#45','MFGR#459','saddle','MEDIUM , \"PLATED\" STEEL',20,'MED CASE'),
(27,'drab cornflower','MFGR#2','MFGR#22','MFGR#2225','plum','LARGE, ANODIZED TIN',20,'MED PKG'),
(28,'honeydew dim','MFGR#2','MFGR#21','MFGR#2130','green','SMALL, \"PLATED\" COPPER',19,'JUMBO PKG'),
(42,'azure bisque','MFGR#1','MFGR#14','MFGR#1414','midnight','MEDIUM BURNISHED TIN',45,'LG BOX'),

INSERT文としてエクスポートされていることが分かります

CSV形式でS3にエクスポートしてみる

今度は少しパターンを変えて試してみます。エクスポートするファイルの形式をcsvに、出力先をS3に変えて実行してみます。

$ tiup dumpling -u <ユーザー名> -P 4000 -h <TiDB Serverlessのエンドポイント> --filetype csv -t 8 -o s3://<S3バケットのパス> -r 200000 -F 4MiB -p <パスワード>

["dump data successfully, dumpling will exit now"]のログを確認後、出力先S3バケットの中身を確認してみました。

S3にエクスポートされたTiDBのデータ 正しくエクスポートできていそうです。

簡単にファイルの中身を確認しておきましょう

$aws s3 cp s3://<バケット名>/<CSVファイル名> - | head
"p_partkey","p_name","p_mfgr","p_category","p_brand1","p_color","p_type","p_size","p_container"
42878,"burnished violet","MFGR#1","MFGR#15","MFGR#1540","dodger","PROMO PLATED STEEL",1,"WRAP DRUM"
42903,"sienna dark","MFGR#3","MFGR#32","MFGR#3230","pink","SMALL BRUSHED BRASS",5,"LG JAR"
42908,"cyan chocolate","MFGR#5","MFGR#54","MFGR#5420","violet","STANDARD BURNISHED COPPER",16,"MED BOX"
42910,"misty cyan","MFGR#2","MFGR#22","MFGR#2240","indian","STANDARD PLATED NICKEL",35,"SM CAN"
42918,"violet purple","MFGR#5","MFGR#51","MFGR#5110","firebrick","STANDARD BRUSHED NICKEL",9,"MED PACK"
42926,"tomato lace","MFGR#3","MFGR#31","MFGR#3139","burlywood","SMALL BRUSHED NICKEL",17,"WRAP CASE"
42932,"bisque green","MFGR#3","MFGR#31","MFGR#3113","pale","STANDARD BRUSHED STEEL",20,"JUMBO PACK"
42946,"tomato lace","MFGR#1","MFGR#11","MFGR#112","rose","SMALL POLISHED TIN",3,"JUMBO CASE"
42948,"navy chiffon","MFGR#2","MFGR#22","MFGR#2221","honeydew","PROMO BURNISHED TIN",29,"SM JAR"
download failed: s3://<バケット名>/<CSVファイル名> to - [Errno 32] Broken pipe

パイプでheadコマンドに渡したのでエラーメッセージが出ていますが、CSVファイル自体は正しくエクスポートされてそうです。

ファイルを圧縮しつつGCSバケットに出力してみる

S3にファイルがエクスポートできたので、今度はGoogle CloudのCloud Storageにエクスポートしてみましょう。せっかくなので--compressオプションを指定してGZIP形式に圧縮しつつやってみます。今度はGoogle CloudのCloud Shellから以下のコマンドを実行します。

$ tiup dumpling -u <ユーザー名> -P 4000 -h <TiDB Serverlessのエンドポイント> --filetype csv -t 8 -o gcs://<バケット名>  -r 200000 -F 4MiB --compress gzip -p <パスワード>

出力後のStorageバケットの様子です

Cloud StorageにエクスポートされたTiDBのデータ

先程のパターンと比較してファイルサイズが小さくなっており、GZIPの圧縮が効いていることが分かります。

GZIP圧縮されたCSVファイルを解凍して簡単に中身を確認してみましょう

$ gsutil cp gs://<バケット名>/<GZIPファイル名> -| gunzip | head
"p_partkey","p_name","p_mfgr","p_category","p_brand1","p_color","p_type","p_size","p_container"
42878,"burnished violet","MFGR#1","MFGR#15","MFGR#1540","dodger","PROMO PLATED STEEL",1,"WRAP DRUM"
42903,"sienna dark","MFGR#3","MFGR#32","MFGR#3230","pink","SMALL BRUSHED BRASS",5,"LG JAR"
42908,"cyan chocolate","MFGR#5","MFGR#54","MFGR#5420","violet","STANDARD BURNISHED COPPER",16,"MED BOX"
42910,"misty cyan","MFGR#2","MFGR#22","MFGR#2240","indian","STANDARD PLATED NICKEL",35,"SM CAN"
42918,"violet purple","MFGR#5","MFGR#51","MFGR#5110","firebrick","STANDARD BRUSHED NICKEL",9,"MED PACK"
42926,"tomato lace","MFGR#3","MFGR#31","MFGR#3139","burlywood","SMALL BRUSHED NICKEL",17,"WRAP CASE"
42932,"bisque green","MFGR#3","MFGR#31","MFGR#3113","pale","STANDARD BRUSHED STEEL",20,"JUMBO PACK"
42946,"tomato lace","MFGR#1","MFGR#11","MFGR#112","rose","SMALL POLISHED TIN",3,"JUMBO CASE"
42948,"navy chiffon","MFGR#2","MFGR#22","MFGR#2221","honeydew","PROMO BURNISHED TIN",29,"SM JAR"

正しくエクスポートされていそうです。

まとめ

TiDBからデータをエクスポートするためのツールDumplingについて調べてみました。MySQLからのデータエクスポートや各種ストレージサービスへのデータ出力にも対応しているのでMySQLからTiDBにデータを移行する際に便利に使えそうだと感じました。他のツール・機能と合わせて覚えておくと便利に使えそうです。

参考

Dumpling Overview | PingCAP Docs