【MySQL】Mysql2::Error::ConnectionError 対処法

`rails server`してサーバーを切り忘れてしまった後にmysqlのエラーが出る。
よくやってしまうので、自分用にまとめました。実際にやっていて手順が増えたら随時追加する。
`mysql  Ver 8.0.19 for osx10.13 on x86_64 (Homebrew)`


## エラー

```console
$ rails s
=> Booting Puma
=> Rails 5.2.4.2 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.4 (ruby 2.5.3-p105), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
Started GET "/" for 127.0.0.1 at 2020-04-02 11:39:55 +0900

Mysql2::Error::ConnectionError - Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2):
```

pumaでrailsサーバーを起動することはできるが、実際にアクセスするとmysqlのエラーが出る。

>Mysql2::Error::ConnectionError - Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2):


## 手順

### $ sudo mysql.server start

```console
$ sudo mysql.server start  # mysqlサーバーを起動
Password:  # アカウントのパスワードを入力
Starting MySQL
... SUCCESS!
```

この表示が出れば、あとは`$ rails server`でオーケーです。
うまく行かなかった場合は↓

```
Starting MySQL
.Logging to '/usr/local/var/mysql/k-end.err'.
 ERROR! The server quit without updating PID file (/usr/local/var/mysql/k-end.pid).
```

```console
$ mysql  # mysqlコマンドも実行できない
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
```

### $ touch /usr/local/var/mysql/k-end.pid

本当はこの前に、対象pidファイルを`k-end.local.pid`にした。ここでは置き換えている。
もしかしたら`k-end.pid`のままではうまく行かないかもしれない。その場合は下記の方法で対象pidファイルを設定すること。

```console
$ ls /usr/local/var/mysql/  # 指定のディレクトリを確認。k-end.pidは存在しない
#innodb_temp                      binlog.index                      ibdata1                           runteq_normal_development
app_development                   ca-key.pem                        ibtmp1                            runteq_normal_test
app_test                          ca.pem                            k-end.local.err                   runteq_rails_advanced_development
auto.cnf                          client-cert.pem                   k-end.local.pid                   runteq_rails_advanced_test
binlog.000001                     client-key.pem                    k_end.local.pid                   server-cert.pem
binlog.000002                     hashlog_development               mysql                             server-key.pem
binlog.000003                     hashlog_test                      mysql.ibd                         sys
binlog.000004                     ib_buffer_pool                    performance_schema                undo_001
binlog.000005                     ib_logfile0                       private_key.pem                   undo_002
binlog.000006                     ib_logfile1                       public_key.pem

$ touch /usr/local/var/mysql/k-end.pid  # k-end.pidを作成
```


### $ sudo chown -R _mysql:_mysql /usr/local/var/mysql/

```console
$ sudo chown -R _mysql:_mysql /usr/local/var/mysql/  # グループと所有者をmysqlにする

$ ls -la /usr/local/var/mysql/  # 権限の確認
total 352544
drwxr-x---   12 _mysql  _mysql       384 May  2 11:35 #innodb_temp
drwxr-xr-x   42 _mysql  _mysql      1344 May  2 11:35 .
drwxrwxr-x    9 k_end   admin        288 Apr 28 15:05 ..
drwxr-x---    5 _mysql  _mysql       160 Apr 21 12:08 app_development
drwxr-x---    2 _mysql  _mysql        64 Apr 21 12:00 app_test
...
-rw-r-----    1 _mysql  _mysql         6 May  2 11:35 k-end.pid
-rw-r--r--    1 _mysql  _mysql      7104 May  2 11:35 k-end.err
-rw-r-----    1 _mysql  _mysql      6659 Apr  2 11:40 k-end.local.err
...
```

### $ touch /tmp/mysql.sock

```console
$ mysql_config --socket  # MySQLで設定されているSocketのパスを確認
/tmp/mysql.sock

$ ls -la /tmp/mysql.sock  # /tmp/mysql.sockが存在するか確認
ls: /tmp/mysql.sock: No such file or directory

$ touch /tmp/mysql.sock  # /tmp/mysql.sockを作成
```

### $ sudo chmod 777 /tmp/mysql.sock

```console
$ sudo chmod 777 /tmp/mysql.sock  # mysql.sockの権限を777にする

$ ls -la /tmp/mysql.sock  # 権限の確認
srwxrwxrwx  1 _mysql  _mysql  0 May  2 11:35 /tmp/mysql.sock
```

```console
$ sudo mysql.server start
Password:
Starting MySQL
... SUCCESS!
```

### $ 再度rails serverでアクセス

今回はこれで解決しました。


## 事象の記録

整ってない。

### 手動でpidファイルを作成した（chownしていない状態）

```console
$ ls /usr/local/var/mysql/
#innodb_temp                      binlog.index                      ibdata1                           runteq_normal_development
app_development                   ca-key.pem                        ibtmp1                            runteq_normal_test
app_test                          ca.pem                            k-end.local.err                   runteq_rails_advanced_development
auto.cnf                          client-cert.pem                   k-end.local.pid                   runteq_rails_advanced_test
binlog.000001                     client-key.pem                    k_end.local.pid                   server-cert.pem
binlog.000002                     hashlog_development               mysql                             server-key.pem
binlog.000003                     hashlog_test                      mysql.ibd                         sys
binlog.000004                     ib_buffer_pool                    performance_schema                undo_001
binlog.000005                     ib_logfile0                       private_key.pem                   undo_002
binlog.000006                     ib_logfile1                       public_key.pem                       
```

`/usr/local/var/mysql/k-end.pid`が存在しないが、`k-end.local.pid`があるのでそれを見てみる。

```console
$ cat /usr/local/var/mysql/k-end.local.pid
1623
```

じゃあこれをコピーして`k-end.pid`にすればいいんじゃね？

```console
$ cp /usr/local/var/mysql/k-end.local.pid /usr/local/var/mysql/k-end.pid
```

```console
$ sudo mysql.server start
Password:
Starting MySQL
.. SUCCESS!
$ Logging to '/usr/local/var/mysql/k-end.err'. # 自動的に表示される
```

MySQLの起動には成功するが、サーバーを起動するとpidファイルが自動的に消えてしまう。
→`$ mysql.server stop`すらできなくなる。

`$ sudo chown -R _mysql:_mysql /usr/local/var/mysql/`コマンドによって解消した。


### my.cnfで対象のpidファイルを設定する

```console
$ mysql --help | grep my.cnf  # このファイルが設定の読み込み対象となる。
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf
```

MySQLが読み込み対象とする`my.cnf`を探しに行く。`/usr/local/etc/my.cnf`しかなかった。

```console
$ cat /usr/local/etc/my.cnf
[mysql]
default-character-set=utf8mb4

[mysqld]
character-set-server = utf8mb4
skip-character-set-client-handshake
collation-server = utf8mb4_general_ci
init-connect = SET NAMES utf8mb4
# Only allow connections from localhost
bind-address = 127.0.0.1
```

```console
$ vi /usr/local/etc/my.cnf

...
[mysqld]
character-set-server = utf8mb4
skip-character-set-client-handshake
collation-server = utf8mb4_general_ci
init-connect = SET NAMES utf8mb4
# Only allow connections from localhost
bind-address = 127.0.0.1
pid-file = /usr/local/var/mysql/k-end.local.pid  # この記述を追加
```


## リンク

- 助かった
  - [mysqlのsocketエラーでrailsアプリが起動できない](https://qiita.com/fujitora/items/d341c52706d1954cae28)
  - [mysql 起動時のThe server quit without updating PID file エラーの回避法](https://qiita.com/jonakp/items/477a18d4a94c01a31583)
- 勉強になった
  - [MySQLの起動、停止ができない場合の対処法](https://beyondjapan.com/blog/2016/03/mysql-stop-start-issues/)
  - [MySQLのソケット場所変更、my.cnfでのsocket設定の注意点](https://easyramble.com/warnings-for-changing-mysql-socket.html)
  - [mysqlが起動できない（Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)）](https://qiita.com/carotene4035/items/e00076fe3990b9178cc0)