TiDB専用のSQLプロキシ TiProxyを使ってみる

1月25日にリリースされた TiDB v7.6.0 DMRにて、TiProxyのコミュニティ版がリリースされました!

https://docs.pingcap.com/tidb/v7.6/tiproxy-overview

TiProxyはTiDBの運用を考慮して、スムーズな接続ができることを目指して作られたMySQLプロトコルのリバースプロキシです。PDからTiDBのトポロジーを取得して接続するため、TiDBのスケールアウトやスケールインに合わせてバックエンドの接続を変更します。通常のロードバランサやリバースプロキシのようにバックエンドの設定やヘルスチェックの設定を行う必要はありません。

実はソースコードリポジトリは前からあって、TiDB Serverlessでは既に使われているプロダクトだったりするのですが、ドキュメントやTiUPでの起動などがサポートされていませんでした。
v7.6.0 DMRのリリースでTiUP Playgroundでも起動するようになっていますので、本記事ではTiUP Playgroundで使ってみます。

## TiUP

[TiUP](https://tiup.io/) はTiDBのコンポーネントをインストールしたり、運用を行ったりする管理コマンドです。TiDB関係の様々なサブコマンドがあり、サブコマンド毎に必要なコンポーネントを自動インストールします。（Linxu/MacOS/WSL用)。インストールは一行でできます。

```bash
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
```

今回利用する `TiUP Playground` はローカル環境でTiDBを起動するコマンドです。

```bash
tiup playground
```
何もオプションを指定しなければ、PD, TiDB, TiKV, TiFlashの最新版（執筆時点で v7.6.0 DMR)が起動します。

### (オプション) TiUPとTiUP Playgroundのアップデート

TiUPを以前インストールしている方は、TiUpとPlaygroundをアップデートします。

```bash
tiup update --self
tiup update playground
```

## TiDBスケールアウト挙動の確認

TiUPの準備ができたら、TiProxyのTiDBスケールアウト時の挙動から確認していきます。

### まずは1台で起動

TiUPを利用して、TiProxyとTiDBそれぞれ1台で起動します。
```bash
tiup playground --db 1 --tiproxy 1 --tiproxy.version v0.2.0
```

TiProxyの最新版はv0.2.0で、こちらを明示的に指定します。TiDBは安定版のv7.5.0を利用することもできますが、ここでは最新版としました。

正常に起動すると、下記のように接続コマンド例が表示されます。TiUP Playgroundでの標準のポートは6000からになっています。

```bash
Connect TiDB:    mysql --comments --host 127.0.0.1 --port 4000 -u root
Connect TiProxy: mysql --comments --host 127.0.0.1 --port 6000 -u root
TiDB Dashboard:  http://127.0.0.1:2379/dashboard
Grafana:         http://127.0.0.1:3000
```

この状態でport 6000に接続して、`SHOW STATUS` で接続しているserver_idを表示します。
```sql
mysql> SHOW STATUS like 'server_id';
+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_id     | 1431969a-6fd3-4e05-a505-30da822f0082 |
+---------------+--------------------------------------+
```

### TiDB 2台にスケールアウトし接続

別のコンソールから、TiUPコマンドを使ってtidbをスケールアウトします。

```bash
tiup playground scale-out --db 1
```

`tiup playground display` で、現在起動しているプロセスとその数が分かります。
```bash
> tiup playground display

Pid    Role     Uptime
---    ----     ------
82313  pd       10m7.157147417s
82314  tikv     10m7.114308709s
82315  tidb     10m7.072096708s
83032  tidb     22.481376625s
82316  tiproxy  10m7.065385833s
82331  tiflash  9m55.115412334s
```

この状態で、また別のコンソールからmysqlクライアントでport 6000に接続し、`SHOW STATUS`でserver_idを確認します。別のサーバに接続していることが分かると思います。

```sql
+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_id     | 41da1811-ed44-427f-a241-1318e7456351 |
+---------------+--------------------------------------+
```

このように、バックエンドのTiDB Serverが増えると、その情報をPDから取得してそちらにも接続を振り分けます。

## スケールイン時の挙動の確認

次に、TiDBをスケールインして、サーバを1台にした際、接続が残った1台に振り替えられるのを確認します。
通常、ロードバランサなどの背後にTiDBを配置した場合は、スケールインに合わせて削除されるインスタンスをバックエンドから外す必要があります。TiProxyはこれを自動で行います。

### スケールイン

TiUP Playgroundのスケールイン時には、削除するTiDBのpidを指定する必要があります。`tiup playground display` で表示されるので番号の若い方を指定します。

```bash
tiup playground scale-in --pid [pid]
```

最初にmysqlクライアントで接続したコンソールに戻り、再度server_idを確認すると、server_idが変わっているのが分かります。今回はセッション張ったままですので切断して再接続されたメッセージが表示されていますが、tidb側で `graceful-wait-before-shutdown` パラメーターを設定することで、新規接続を別のTiDBに振りつつ、既存のコネクションがクローズするまで一定時間待つよう設定することもできます。

```sql
mysql> show status like 'server_id';
ERROR 2013 (HY000): Lost connection to MySQL server during query
No connection. Trying to reconnect...
Connection id:    16
Current database: *** NONE ***

+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_id     | 41da1811-ed44-427f-a241-1318e7456351 |
+---------------+--------------------------------------+
```