PlanetscaleからTiDB Serverlessにデータを移行する

# はじめに
PlanetscaleのHobbyプランが4月8日に終了することが発表されました。

https://planetscale.com/blog/planetscale-forever

[TiDB Serverless](https://www.pingcap.com/tidb-serverless/) は、同じくMySQL互換のサーバレスデータベースで、クレジットカード不要で無料枠があります。 移行先として是非利用を検討してみてください。

PlanetscaleからTiDB Serverlessへのデータ移行方法について紹介していきます。

## 移行手段

TiDBもMySQL互換のため、基本的にはMySQLツール群、SQLが利用できますが、移行に関しては二点考慮点があります。

:::note warn
Planetscaleはsqlでのデータ出力に`10万行`の制限があります。このため、このデータ量を超える場合は単純なmysqldump & mysqlimportでの移行はできません。
:::
:::note warn
TiDB Serverlessは現時点でMySQL 5.7互換のv7.1.1です。そのため、Planetscaleの標準COLLATIONの`utf8mb4_0900_ai_ci` に対応していません。
:::

https://x.com/bohnen/status/1765661453493862416?s=20

この記事では、これらを考慮した移行方法をご紹介したいと思います。利用環境はMacOSを想定していますが、Bash/Zshコンソールが利用出来る環境であれば同じ手順で移行できると思います。

## 前提条件

- Bash/Zshが利用できること
- [pscale CLI](https://planetscale.com/features/cli) がインストール済みであること
- MySQL clientがインストール済みであること 

## 移行手順

### データのエクスポート

データのエクスポートには、pscale cliを利用します。`pscale database dump [db] [branch]` です。

```bash
> pscale database dump testdb2 main
Starting to dump all tables from database testdb2 to folder /Users/bohnen/.../pscale_dump_testdb2_main_20240307_164703
Dumping is finished! (elapsed time: 6.782051792s)
```
今回は700MBくらいのデータを利用しましたが、10万行の制限を超えていても問題なくダウンロードできています。

データは、新しく作成されたディレクトリの中に、スキーマファイルとデータファイルの形でエクスポートされています。
```bash
> ls
metadata 
testdb2.history-schema.sql
testdb2.new_order.00001.sql
testdb2.stock-schema.sql
...
```

基本的にはこのsqlを順次実行すれば、データ移行は完了します。

### スキーマの変更

TiDB Serverlessではまだ`utf8mb4_0900_ai_ci`に対応していないので、一律変換します。

:::note
TiDB Dedicatedで提供されている最新のLTS, v7.5.1では`utf8mb4_0900_ai_ci`はサポートされています。詳細は[公式Doc](https://docs.pingcap.com/ja/tidb/stable/character-set-and-collation#character-sets-and-collations-supported-by-tidb)を参照してください。
:::

```bash
cd [exportしたディレクトリ]
for f in *-schema.sql; do sed -i -e  's/0900_ai_ci/bin/' $f; done;
```

### データベースの作成

TiDB Serverlessクラスタを起動しておきます。
TiDBに接続して、データのインポート先であるデータベーススキーマを作成しておきます。

:::note
TiDB Serverlessが初めての方は、[こちら](https://qiita.com/urachooooooo/items/353ea1973ce5f51448ea)の入門記事をご覧ください
:::

Chat2Queryで作成してもよし、MySQL clientで接続してもよいです。
```sql
CREATE DATABASE [データベース名];
```

### テーブルの作成

`schema.sql` を流していきます。TiDB Serverlessへ MySQL clientで接続していきます。
```bash
for f in *-schema.sql; 
do mysql --comments -u [user] -h gateway01.ap-northeast-1.prod.aws.tidbcloud.com -P 4000 -D [database] --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p[password] < $f ; 
done;
```
※実際は一行ですが見やすさのために改行しています。[user][password][database]はご自身のものをご利用ください。

### データのインポート

同様に、`00001.sql` を流していきます。
```bash
for f in *[0-9].sql; 
do mysql --comments -u [user] -h gateway01.ap-northeast-1.prod.aws.tidbcloud.com -P 4000 -D [database] --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem -p[password] < $f ; 
done;
```

これで完了です。

## 消費RU確認

TiDB Serverlessは5GB、5000万RU(Request Unit)分は無料です。

https://pingcap.co.jp/tidb-cloud-serverless-pricing-details/

このRUの計算は難しいですが、だいたい書込容量に等しいです。今回700MB程度のデータをImportしてみた消費RUを確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/9d19e27c-29a0-d754-93ae-c92d4276047f.png)

これは他のデータが元々700MBほど入っていたクラスタなのでストレージ容量は正確ではありませんが、
- 今回消費したRUは7.42M
- 消費したRow-based Storageは500MB強（TiDBでの圧縮後)

となりました。データインポート後もまだまだ無料でご利用いただけます。

是非、TiDB Serverlessを使ってみてください。