Mysql2::Error::ConnectionError: Access denied for user 'root'@'localhost' (using password: NO)を解決する方法

# やりたいこと
MySQLでデータベースを作りたい。

# 問題
データベースを作成しようとするとエラーが出た。
エラーを解決してデータベースを作成した。

# エラー文

```
naota7118@Naotas-MacBook-Air-6 my_dictionary % rails db:create                             
Access denied for user 'root'@'localhost' (using password: NO)
パスワードを使わずに'root'@'localhost'というユーザーでアクセスしようとしたら拒否されました
Couldn't create 'my_dictionary_development' database. Please check your configuration.
rails aborted!
'my_dictionary_development'というデータベースを作成できませんでした。設定を確認してください。
Mysql2::Error::ConnectionError: Access denied for user 'root'@'localhost' (using password: NO)
MySQLにアクセスできないエラー：パスワードを使わずに'root'@'localhost'というユーザーでアクセスしようとしたら拒否されました
```

# どのような時にこの問題が起きるのか？
MySQLに設定しているパスワードと自分のアプリケーションのdatabase.ymlで設定したパスワードが不一致の場合に起きる。

# どのように解決すればいいのか？
① MySQLにパスワードを設定しているかを確認する。
② database.ymlでパスワードを設定しているか確認する。
③ MySQLのパスワードとdatabase.ymlのパスワードが一致するように、どっちか、あるいは両方を修正する。

# MySQLのパスワードの設定・変更する方法

最初にこのコマンドを打ちます。

```
$ mysql_secure_installation
```
そうすると、このような画面になります。

```
naota7118@Naotas-MacBook-Air-6 my_dictionary % mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
　　　このスクリプトのすべての部分を実行することは、すべてのMySQLに推奨されます
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
      本番環境で使用されているサーバー、各ステップを注意深くお読みください！

In order to log into MySQL to secure it, we'll need the current
password for the root user.  
MySQLを保護する目的でMySQLにログインするためには、
rootユーザーとしての現在のMySQLパスワードが必要です。
If you've just installed MySQL, and you haven't set the root password yet, 
the password will be blank, so you should just press enter here.
MySQLをインストールしたばかりで、rootパスワードをまだ設定していない場合、
パスワードは空白になるため、ここでEnterキーを押すだけです。

Enter current password for root (enter for none): 現在のパスワードを入力（すでにパスワードを設定してる場合）
                                                  Enterキー（パスワードを設定してない場合）
```
入力が正しければ下記の画面になります。

```
OK, successfully used password, moving on...
使用されたパスワードがうまくいったので、先に進みます...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.
rootパスワードを設定すると、適切な認証なしに、誰もMySQLrootユーザーにログインできなくなります。
（そもそもパスワードってそういうものですよね...）
You already have a root password set, so you can safely answer 'n'.
すでにrootパスワードが設定されているので、安全に「n」と答えることができます。
（パスワードを変更しないならnを押せということでしょう...?）

Change the root password? [Y/n] y を入力します
パスワードを変更しますか？YesならY, Noならn
```
y と入力すると新しいパスワードを入力するように言われます。
ちなみに、今のパスワードと全く同じのを入力してもエラーにはなりません。

```
Change the root password? [Y/n] y
New password: 新しいパスワードを入力
```

もう１回新しいパスワードを入力するように言われるので、入力しましょう

```
Change the root password? [Y/n] y
New password: もう１回新しいパスワードを入力
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.
デフォルトでは、MySQLインストールには匿名ユーザーが含まれているため、
ユーザーアカウントを作成しなくても誰でもMySQLにログインできます。
これはテストのみを目的としており、インストールを少しスムーズにすることを目的としています。
本番環境に移行する前に、それらを削除する必要があります。

Remove anonymous users? [Y/n] y を入力
```
他の誰かのパソコンから侵入されることを防ぐために、自分のパソコンからの接続のみを許可する設定にします。

```
Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.
通常、rootは「localhost」からの接続のみを許可する必要があります。
これにより、誰かがネットワークからルートパスワードを推測できないようになります。

Disallow root login remotely? [Y/n] y を入力
rootログインをリモートで禁止しますか？
```
テスト用のデータベースは必要ないため削除します。
Rspecを使ったテストでデータベースを使う場合はnと入力しましょう。

```
Disallow root login remotely? [Y/n] y
 ... Success!

By default, MySQL comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.
デフォルトでは、MySQLには「test」という名前のデータベースが付属しており、誰でもアクセスできます。
これもテストのみを目的としているため、本番環境に移行する前に削除する必要があります。

Remove test database and access to it? [Y/n] y を入力
```

privilege tablesが何を指しているのかが分かりませんが、ここまで行ってきた変更を反映させるための操作です。

```
emove test database and access to it? [Y/n] y
 - Dropping test database...
ERROR 1008 (HY000) at line 1: Can't drop database 'test'; database doesn't exist
 ... Failed!  Not critical, keep moving...
 - Removing privileges on test database...
 ... Success!
今回はまだデータベースを作れていない段階でのエラだったため、テスト用のデータベースはないよと言われました...
すでにデータベースを作成済みであれば、このようなエラーは出ないはずです。

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
特権テーブルを再ロードすると、これまでに行ったすべての変更がすぐに有効になります。

Reload privilege tables now? [Y/n] y と入力
```
お疲れ様でした！これでパスワードの再設定は完了です！

```
Reload privilege tables now? [Y/n] y
 ... Success!

All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.
全部終わった！上記のすべての手順を完了すると、MySQLのインストールは安全になります。
Thanks for using MySQL!

Cleaning up...
naota7118@Naotas-MacBook-Air-6 my_dictionary % 
```

# アプリケーションのdatabase.ymlのパスワードを確認・変更する
ちょっと見づらいかもしれませんが、開発環境だったら「パスワード１」、本番環境だったら「パスワード２」のところを、先ほど設定したMySQLのパスワードと同じパスワードに設定しましょう。

```ruby:database.yml:config
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: ☆パスワード１☆
  socket: /tmp/mysql.sock

development:
  <<: *default
  database: my_dictionary_development

test:
  <<: *default
  database: my_dictionary_test

production:
  <<: *default
  database: my_dictionary_production
  username: my_dictionary
  password: ☆パスワード２☆
```

MySQLのパスワードとdatabase.ymlのパスワードが一致するように設定できれば、下記のようにデータベースが問題なく作成できるようになります。

```
naota7118@Naotas-MacBook-Air-6 my_dictionary % rails db:create          
Created database 'my_dictionary_development'
Created database 'my_dictionary_test
```

# ポリシー要件を守っていないと言われたら...
```
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
```
デフォルトのルールでは、**「パスワードの長さが8文字以上, 小文字/大文字両方が含まれており, 特殊文字が含まれていること」**と、パスワードの要件が決められています。

それを守っていないと、上記のエラーが出ます。

ベストプラクティスはこのルールを守ったパスワードを設定することなのですが、結構大変なので、下記の記述を追加することで、パスワードのバリデーションをOFFにするのも１つです。

```
$ sudo vi /etc/my.cnf
```
上記のコマンドで`/etc/my.cnf`を開きます。

```
[mysqld]
validate-password=OFF
```

上記の記述を追加します。

設定を反映させるためにMySQLを再起動しましょう。
MySQLを再起動させる方法はいくつかあるので、ご自分に合う方法でやって頂ければと思います。
（下記のコマンドは両方やる必要はなく、どちらかうまくいく方だけで大丈夫です）

```
$ sudo systemctl restart mysqld.service
$ sudo mysql.server restart
```



# 参考記事
- [CentOS で mysql を入れたらroot パスワードどこよ？ってなった](https://takuya-1st.hatenablog.jp/entry/2016/07/01/183342)
- [MySQL 5.7 をインストールしたら最初に行うセットアップ](https://weblabo.oscasierra.net/mysql-57-init-setup/)
- [Mysql 5.7* パスワードをPolicyに合わせるとめんどくさい件について](https://qiita.com/keisukeYamagishi/items/d897e5c52fe9fd8d9273)