#1.MySQLでUNIXドメインソケット通信とTCP/IP通信の比較

# はじめに
この記事では、同一ホストでMySQLへ接続する際にUNIXドメインソケット通信とTCP/IPソケット通信のどちらが適しているのかを検証していきたいと思います！<br>

- UNIXドメインソケット通信＝プロセス間の通信に用いられる通信で、.sockファイルを使用して同一ホスト内で通信を行うことができる。
- TCP/IPソケット通信＝IPアドレスとポート番号を用いてリモートホスト間での通信を行うことが可能。
# 環境
- AmazonLinux2
- MySQL 8.0

## UNIXドメインソケット通信で接続
まずMySQLへUNIXドメインソケット通信で接続してみます。
```
# mysql -u root -p 
```
```
mysql> SHOW PROCESSLIST;
+----+-----------------+-----------+------+---------+-------+------------------------+------------------+
| Id | User            | Host      | db   | Command | Time  | State                  | Info             |
+----+-----------------+-----------+------+---------+-------+------------------------+------------------+
|  5 | event_scheduler | localhost | NULL | Daemon  | 53946 | Waiting on empty queue | NULL             |
| 14 | root            | localhost | NULL | Query   |     0 | init                   | SHOW PROCESSLIST |
+----+-----------------+-----------+------+---------+-------+------------------------+------------------+
2 rows in set, 1 warning (0.19 sec)
```
- Id=クエリのプロセスID
- User=クエリを実行したユーザー
- Host=接続元のホスト名、ポート番号
- db=接続しているデータベース名。なしの場合はNULL
- Command=クエリの状態
- Time=クエリが完了するまでの時間
- Info=クエリののステータス

`root`ユーザーのHostが`localhost`のみとなっておりUNIXドメインソケット通信を行っているように見えます。
※ローカル接続はデフォルト設定の場合、UNIXドメインソケット通信で接続を行います。
```
# netstat -anp | grep "mysql"
unix  2      [ ACC ]     STREAM     LISTENING     58851    9765/mysqld          /var/lib/mysql/mysql.sock
unix  3      [ ]         STREAM     CONNECTED     175971   9765/mysqld          /var/lib/mysql/mysql.sock
```

- unix=プロトコル

- 数値=ソケットを参照しているプロセスの数です。

- ([ ACC ] / [　　])=ソケットの状態に関するフラグ。
ACC はアクセプト可能（接続を受け入れる準備ができている）であることを示す。
フラグが空の場合は、接続されている状態（CONNECTED）。

- (STREAM / DGRAM)=ソケットの通信タイプ。
STREAM: TCPのような接続指向の通信（シーケンシャルデータの送受信）。
DGRAM: UDPのような接続のないデータグラム通信。

- (LISTENING / CONNECTED)=ソケットの状態。
LISTENING: ソケットが接続要求を待っている状態です（サーバー側がクライアントからの接続を待ち受けている）。
CONNECTED: ソケットが他のプロセスと接続されている状態。

- (58851 / 177319 など)=inode番号 

- (9765/mysqld)=ソケットを使用しているプロセスのID（PID）とその名前。

 - (/var/lib/mysql/mysql.sock /など)=ソケットのパス

```
# time mysql -u root -p -e "SELECT 1;"                                                          
Enter password: 
+---+
| 1 |
+---+
| 1 |
+---+

real    0m3.639s
user    0m0.004s
sys     0m0.004s
```

real=プログラムの呼び出しから終了までにかかった実時間（秒）
user=プログラム自体の処理時間（秒）
sys=プログラムを処理するために、OSが処理をした時間（秒）


参考リンク
https://qiita.com/tossh/items/659e5934e52b38183200

realの数値を参考にすればよいと思うので合計で5回計測して平均値を出す。
以下、計測結果

real    0m3.182s
real    0m3.100s
real    0m3.639s
real    0m2.866s
real    0m2.801s
avg     0m3.117s

ベンチマークテストも一応行ってみる。
同一ホストでクライアントが増えることはほぼないと思うけど参考程度で。
```
# mysqlslap -c 10 -i 5 -u root -p --create-schema=wordpress_db --query="SELECT 1;"
Enter password:
Benchmark
        Average number of seconds to run all queries: 0.012 seconds
        Minimum number of seconds to run all queries: 0.006 seconds
        Maximum number of seconds to run all queries: 0.021 seconds
        Number of clients running queries: 10
        Average number of queries per client: 1
```
## TCP/IP通信で接続
続いてTCP/IPで接続してみます。
```
# mysql -u root -p -h 127.0.0.1
```
```
mysql> SHOW PROCESSLIST;
+----+-----------------+-----------------+------+---------+-------+------------------------+------------------+
| Id | User            | Host            | db   | Command | Time  | State                  | Info             |
+----+-----------------+-----------------+------+---------+-------+------------------------+------------------+
|  5 | event_scheduler | localhost       | NULL | Daemon  | 57276 | Waiting on empty queue | NULL             |
| 19 | root            | localhost:55436 | NULL | Query   |     0 | init                   | SHOW PROCESSLIST |
+----+-----------------+-----------------+------+---------+-------+------------------------+------------------+
2 rows in set, 1 warning (0.00 sec)
```
今度は`root`ユーザーのHostに`localhost:55436`が表示されてポート番号(55436)も表示されました。

`netstat`コマンドでデフォルトのポート番号`3306`を検索してみます
```
# netstat -anp | grep "3306"
tcp        0      0 127.0.0.1:55436         127.0.0.1:3306 
```
- tcp=プロトコル
- 0 0=最初の数字（0）は送信バッファ内の未送信データの量を示す。
次の数字（0）は受信バッファにある未処理のデータの量を示す。
どちらもゼロということは、未送信および未処理のデータがない状態を意味する。
- 127.0.0.1:55436=ローカルホストのIPアドレス:MySQLに接続するために使用しているポート番号
- 127.0.0.1:3306=サーバーのIPアドレス(ローカルホスト):サーバー側のポート番号。
```
# time mysql -u root -p -h 127.0.0.1 -e "SELECT 1;"
Enter password: 
+---+
| 1 |
+---+
| 1 |
+---+

real    0m4.798s
user    0m0.006s
sys     0m0.007s
```


こちらも平均値を出してみる
real    0m4.798s
real    0m4.800s
real    0m3.850s
real    0m3.223s
real    0m3.182s
avg     0m3.970s

わずかにUNIXドメインソケット通信のほうが早いように見える

ベンチマークテストも一応行ってみる。
 ```
# mysqlslap -c 10 -i 5 -u root -p -h 127.0.0.1 --create-schema=wordpress_db --query="SELECT 1;"
Enter password: 
Benchmark
        Average number of seconds to run all queries: 0.093 seconds
        Minimum number of seconds to run all queries: 0.041 seconds
        Maximum number of seconds to run all queries: 0.290 seconds
        Number of clients running queries: 10
        Average number of queries per client: 1
```

こちらはわかりやすく差が出ましたね。


## まとめ
わずかながらにUNIXドメインソケット通信のほうがパフォーマンスがよい、という結果になりました。
個人的にはmy.cnfの設定をいじればデフォルトの通信の設定をTCP/IPに変更することも可能とのことなので、
差があまりないようであれば、汎用性を考えてTCP/IP通信をデフォルトにして使っていく方がよいのではないかと思いました。