PlanetScaleというサーバレスDBの開発体験がとても良かった話

国内でも既にいくつかPlanetScaleを紹介した記事はありますが、スケーラビリティやノンブロッキングスキーマ変更などのDBとしての機能にフォーカスした記事が多い印象です。

個人的には、そこの機能以上に **DBの世界にBranchingやDeploy Request(GithubでいうPull Request的なもの)という概念を導入** して、**日々の開発体験をデザインしなおそうとしているところ** の部分が今までのサービスと違って面白いと感じたので、この記事ではそこを中心に紹介してみたいと思います。

## PlanetScale is 何

https://planetscale.com/

- Full ManagedなMySQL8ベースのDB
- ノンブロッキングなスキーマ変更機能を持つ
- オートスケール機能があり、かつ大規模なレベルまでスケール可能
- 現時点でもYouTube, Slack, Github, Shopifyなどなどの多くのTech Giantsな企業で利用されている
- 5GBまでなら無料
- **開発環境〜本番環境まで扱うことを前提としたワークフローが用意されており、それを実現するためのBranchingやDeploy Requestといった機能が存在する <-- (この記事では、ここを中心に紹介)**

## PlanetScaleにおけるブランチとは？

従来、本番環境DB・ステージング環境DB・開発環境DBなど、従来はそれぞれの用意方法、扱い方法、開発結果の適応方法などを考える必要がありました。

PlanetScaleではブランチという機能を使うことで独立した環境を即作成・その変更内容を安全に適応などを行う仕組みが用意されており、サービス自体に複数環境を管理する仕組みが組み込まれていると言えます。

さらにブランチ(DB環境)を気軽に作ることができることで **普段コードを書く時に行っている 「開発内容ごとにブランチを用意して、本番とに差分を確認して、レビューして、本番に反映する」といったフローをDBの世界でも行うことができます。**

## 環境の用意

実際に使い方をみていってみましょう。
まず、普段の開発ワークフローの前に、環境一式を用意しておきます。

以下のような本番環境を作っていきます。
- `my-example-db` というDBがある
- 本番環境(mainブランチ)には `products`テーブルがあり、`name`と`description`というフィールドが存在する


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

 [PlanetScale](https://planetscale.com)のアカウント作成して、[PlanetScale CLI ](https://planetscale.com/cli)( `pscale`コマンド) のInstallまでは行ってる想定で進めていきます。

DB作成は`pscale database create <database>` というコマンドでDBを作成できます。( **1コマンドで本番上にDBが作成できる便利体験！** )

```sh
% pscale database create my-example-db                                                           
```

完了後に表示されたURLを開くと、そのDBのダッシュボードが表示され、**Web Console上から発行されたクエリ、DBのアクセス行数、コネクション数、ストレージなどの状況が確認できます。便利！** 

#### 2. mainブランチに初期データを入れてみる

DBを作成すると `main`というブランチが作成されますので、このブランチに初期スキーマを登録してみます。

`pscale shell <database> <main>`というコマンドだけで、DB Shellに接続できます。 ( **pscale以外に何もいれなくても、DBにつないで直接操作できるの便利！** )

```
% pscale shell my-example-db main
my-example-db/main>
```

以下のクエリを実行してテーブルを作成しておきます。

```sql
CREATE TABLE products (
  id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name varchar(255) NOT NULL,
  description varchar(1024) NOT NULL
);
INSERT INTO products (name, description) VALUES  ('Pen', 'Super nice pen');
```

#### 3. mainブランチをproductionとして設定する

ブランチには `production`と`development`という概念があります。
`production`に設定されたブランチは「本番用トラフィックのため、高い可用性をもつ」、「直接スキーマ変更できない」、「デイリーで自動バックアップされる」などの特徴があります。

`main`ブランチを本番に利用することが一般的なので、今回も`main`ブランチを`production`に昇格させておきます。

```
%  pscale branch promote my-example-db main                                                   ```
```

#### 4. mainブランチのパスワードを発行

初期データを入れた際は `pscale shell` コマンドで接続しましたが、本番のアプリケーションからはhostやpassを指定して接続する必要があります。

パスワードの管理も`pscale`コマンド上から行うことができ、発行は以下のようにします。

```
% pscale password create my-example-db main my-pass
```

上記コマンドを実行すると、`main`ブランチDBにつなぐためのhostやpasswordが発行されます。

## PlanetScaleの開発ワークフロー

さて番環境が準備できたので、いよいよ日々の開発がどのように進むのか見てみましょう。
`products`テーブルにカラムをいくつか追加する、といった変更を考えてみます。

#### 1. 開発ブランチの作成

カラム追加をやりたいので、`add-columns`というブランチを作ってみます。
ブランチは`pscale branch`コマンドで作れます。( コマンド使わずにWeb画面経由からでも簡単に作れます )

```
% pscale branch create my-example-db add-columns
```

```
Branch add-columns was successfully created.

View this branch in the browser: https://app.planetscale.com/xxxxx/my-example-db/add-columns
```

作成完了すると、そのブランチを管理するためのWeb ConsoleのURLが表示されます。
( **Web Consoleから「開発ブランチへのクエリ実行」、「開発ブランチのスキーマ確認」などなどできて便利！** )

#### 2. 開発ブランチへの接続

作ったブランチを使って開発を進めていくわけですが、開発するアプリケーションからDB接続する必要があります。

mainブランチでやったように `pscale password create` コマンドを使うと、このbranch用のパスワードを発行することはできますが、発行の手間もかかるのと、接続情報をアプリケーションのコード上にも反映する手間もかかります。

PlanetScaleには、これらを解決する仕組みとして`pscale connect`コマンドが用意されています。

```
% pscale connect my-example-db add-columns
```

```
Secure connection to database my-example-db and branch add-columns is established!.

Local address to connect your application: 127.0.0.1:3306 (press ctrl-c to quit)
```

上のコマンドは指定した`add-columns`ブランチDBとの接続を安全にProxyして、ローカル上のMySQLとして接続できます。
なので、アプリケーションの接続設定に以下のようにproxy先の情報を記載すれば繋がります。

```
DATABASE=my-example-db
HOST=127.0.0.1
PORT=3306
```

この仕組みで、branchごとにパスワードを発行したり、そのパスワードをいちいちアプリケーションに設定することなく、`pscale connect`コマンドを叩くだけでアプリケーションの接続先のDBを切り替えることができます。( **DBの開発体験向上のための仕組みを、徹底的に整えていこうとしている感..!** )

#### 3. 開発ブランチでスキーマ変更

実際にカラム追加を行ってみます。

本来は先ほど説明した`pscale connect`コマンドでたてたProxyを経由して、アプリケーションで導入しているORMやマイグレーションツールを通じてスキーマ変更を行うことになると思いますが、今回は仮で直接クエリを叩いて実行してみます。

```
% pscale shell my-example-db main add-columns
```

```sql
ALTER TABLE products ADD image_url varchar(1024) NOT NULL DEFAULT 'https://example.com/no_image.png';
```

これでスキーマが変更できたはずです。以下のコマンドを実行するとmainブランチとスキーマとの差分があるかを確認することができます。 ( **Gitでコード開発してるように、スキーマ変更を進めていける!** )

```diff
% pscale branch diff my-example-db add-columns
```

```diff
CREATE TABLE `products` (
        `id` int NOT NULL AUTO_INCREMENT,
        `name` varchar(255) NOT NULL,
        `description` varchar(1024) NOT NULL,
+       `image_url` varchar(1024) NOT NULL DEFAULT 'https://example.com/no_image.png',
        PRIMARY KEY (`id`)
 ) ENGINE InnoDB,
   CHARSET utf8mb4,
   COLLATE utf8mb4_0900_ai_ci;
```

本来は、このタイミングでアプリケーション側の開発と動作確認を行います。
**ちなみにWeb Consoleからは以下のように、このブランチに対して発行されたクエリなどが見れるなどデバッグや動作確認が捗る機能も多々用意されています**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36581/cb0cffbe-87de-6177-de87-5e485476ac90.png)


変更したスキーマが意図通りにうごいているようでしたら、デプロイリクエストを作成します。

#### 4. デプロイリクエストの作成

`pscale deploy-request` コマンドでdeploy-requestを作ることができます(  コマンド使わずにWeb画面経由からでも簡単に作れます )

```
% pscale deploy-request create my-example-db add-columns
```

```
Deploy request #1 successfully created.

View this deploy request in the browser: https://app.planetscale.com/xxxxxxx/my-example-db/deploy-requests/1
```

Deploy RequestのURLが出力されるのでブラウザで開くと詳細が見れます。
画面は以下のようになっており、アクショがタイムライン形式で表示されており、GithubのPull Requestのイメージに近いと思います。コメントやApproveなどが行えるので、コード管理と同じようなレビューフローを挟むことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36581/ea59318a-6252-fe53-4a4d-53699903c7f4.png)


`Scheme Changes`を押すと、以下のように元ブランチとの差分を見ることもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36581/d7ccd551-90a0-c66b-5121-db82fef192bf.png)

**というようにコードで普段やっている、差分をレビューして承認、のようなことがDBの世界でも行えるようになるイメージです**


#### 5. デプロイ

以下の`Deploy changes`ボタンを押すと、変更が元ブランチである`main`ブランチに反映されます。
変更はNon-Blcokingで行われるため、ダウンタイムなくスキーマ変更を実施することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36581/b29db49c-7e84-2af2-17c5-e08db377346d.png)

完了すると以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36581/0e66eed8-9fb7-5dae-125d-0a6daeaa593a.png)

このデプロイはコマンド経由でも行えるため、**CIなどに組み込むことも、もちろん可能です**

## まとめ

ということでPlanetScaleを触ってみて、開発体験がすごく良かったり、ブランチの概念の面白さを感じたので、もっと知ってもらえればと思い、記事を書いてしまいました。

とにかく開発体験(DX)を考えて作られたManaged DBサービスだと感じました。ブランチ機能、豊富なCUIコマンドなどは、本番だけでなく、普段の開発環境での作業効率を大きく向上させる可能性があると思います。

さらに、それでいて「ノンブロッキングなスキーマ変更機能」や「大規模にまでオートスケールできる機能」がついていて、無料ではじめることができるのはスゴイ。

## Q&A

- **コマンド、いっぱい覚えないと使えない？**
  -  コマンドで出来ることは、ほぼほぼWeb画面上からでも操作できるのでポチポチでいけます
- **ブランチごとにスキーマは元ブランチからコピーされるけどデータはどうなるの？**
  -  デフォだとスキーマのみコピーされます。ただ [Data Branching](https://planetscale.com/docs/concepts/data-branching)という仕組みがあり、それを有効にしておくとブランチ作成時に、mainブランチのデイリーバックアップからデータをコピーするような挙動にできるようです
- **コード上でもスキーマ管理していたら、PlanetScale上でのレビューって意味ないのでは？**
  -  そういうケースもあるかもしれません。ただ多くのマイグレーションツールは、宣言的な記述方法と独自のモデリング記法を採用しており、コードをみただけでは実際にどのようにスキーマが変化するか正確に予測が難しいことが多く、そのようなケースでは、まさに役立ちそうです。