MySQLの接続についてdatabase.ymlに書ける設定

Railsアプリでデータベースに接続する設定は`config/database.yml`に書いたり、`DATABASE_URL`環境変数を設定したりして、与える。`database.yml`に書ける内容についての情報がいまいちまとまっていない感じで、調べるのに苦労したのでまとめておく。

# 設定の例

Rails Guidesに書かれた[MySQL設定の例](https://edgeguides.rubyonrails.org/configuring.html#configuring-a-mysql-or-mariadb-database)を見ると、こんな感じ。

```
development:
  adapter: mysql2
  encoding: utf8mb4
  database: blog_development
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock
```

実用上は、大体ここに書いてあることを設定すればそれで良い。

他にありがちな設定としては、`socket`ではなく`host`と`port`を使うこともあったり、`sslca`のようなオプションを渡したりすることだと思う。

# 設定の分類

ActiveRecordの設定は、

1. Connection poolに関するもの
2. MySQLの接続に関するもの

の二つがある。

# Connection poolの設定

Connection poolの設定には、`pool`、`idle_timeout`、`checkout_timeout`があるらしい。

* https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L61-L72

# MySQLの接続に関するもの

MySQLに関する設定はActiveRecordによって処理されるものとmysql2 gemによって処理されるものがあり、一覧としては次の通りになる。

* `host` (mysql2)
* `username` (mysql2)
* `password` (mysql2)
* `port` (mysql2)
* `database` (mysql2)
* `socket` (mysql2)
* `flags` (mysql2, activerecord)
* `encoding` (mysql2, activerecord)
* `read_timeout` (mysql2)
* `write_timeout` (mysql2)
* `connect_timeout` (mysql2)
* `connect_attrs` (mysql2)
* `reconnect` (mysql2)
* `local_infile` (mysql2)
* `secure_auth` (mysql2)
* `ssl_mode` (mysql2)
* `default_file` (mysql2)
* `default_group` (mysql2)
* `default_auth` (mysql2)
* `init_command` (mysql2)
* `sslkey` (mysql2)
* `sslcert` (mysql2)
* `sslca` (mysql2)
* `sslcapath` (mysql2)
* `sslcipher` (mysql2)
* `sslverify` (mysql2)
* `wait_timeout` (activerecord)
* `variables` (activerecord)
* `strict` (activerecord)
* `collation` (activerecord)
* `statement_limit` (artiverecord)
* `prepared_statements` (activerecord)

たくさんあるし、ソースコードをざっと眺めただけなので、もしかしたら欠けているものがあるかもしれない。

`(mysql2)`と書いたものは、mysql2 gemに渡されて処理されるものなので、ドキュメントを読むこと。

* https://github.com/brianmario/mysql2#connection-options

`(activerecord)`と書いたものは、ActiveRecordによって処理されるもので、とりあえずわかった限りで書いておく。

## `flags`

ActiveRecordはmysql2 gemに渡す`flags`をYAMLで良い感じに書くためのサポートを提供している。mysql2のドキュメントに書いてある。

## `encoding`, `collation`

`encoding`と`collation`が指定されているとき、ActiveRecordはMySQLとの接続を確立したときにSQLを自動で発行する。

* https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#L772-L776

MySQLで日本語や絵文字を扱うときに重要な設定なので、各自で確認すること。

## `wait_timeout`

* https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#L745-L748

`wait_timeout`はMySQLの設定に出てくるものと同じで、MySQLに接続したクライアントが切断されるまでのタイムアウトを秒数で指定する。

* https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_wait_timeout

指定がない場合、RailsがMySQLで設定できる最大の値に自動で設定する。

ちなみに、`variables`経由では`wait_timeout`は指定できない。（Railsが上書きしてしまうから。）

## `variables`

* https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#L779-L786

`variables`に書かれている設定をActiveRecordはセッションの設定として指定する。

## `strict`

* https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#L752-L767

この項目には`default`または`true`か`false`が書ける。省略すると`true`になる。

`default`のときはMySQLのサーバの設定をそのまま見る。`true`のときには、`STRICT_ALL_TABLES`になる。`false`のときには、サーバの設定を元に`STRICT_ALL_TABLES`と`STRICT_TRANS_TABLES`と`TRADITIONAL`が**無効になった**設定になる。

* https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html

これは要するに`sql_mode`の設定なので、`variables`で設定することもできる。（`variables.sql_mode`で設定したものが優先される。）

## `statement_limit`, `prepared_statements`

なんか指定できる。（良くわからない。）

# `DATBASE_URL`環境変数経由では？

クエリパラメータとして上記のオプションが設定できる。書いてないものは`database.yml`のものが使われる。

が、`variables`は指定できない気がする。`mysql2://host/db?variables[sql_mode]=STRICT_TRANS_TABLES`などとしても効果がなかった。