MySQLでERROR 1045 (28000): Access denied for userと出てDDL文が実行できなかったときのメモ

###環境
VirtualBox 6.1にCentOS７をインストールして、その中にMySQLをイントールしてteratermで接続。
図にしてみたらこんな感じ？？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/eba959b6-f901-711a-ab83-c54b94c3f973.png)



```
$ cat /etc/centos-release
CentOS Linux release 7.9.2009 (Core)
$ mysql --version
mysql  Ver 8.0.25 for Linux on x86_64 (MySQL Community Server - GPL)
```


###エラーメッセージ

```
$ mysql -umakoto -p < Dump20210429.sql
Enter password:
ERROR 1045 (28000): Access denied for user 'makoto'@'localhost' (using password: YES)
```



###結論（原因）

```
ユーザー登録で'makoto'@'%'として、ホスト名にワイルドカードをしようしていた。
これがすべて。
```

###'ユーザー名'でログインするとAccess deniedになるのはなんで？ユーザー作成しましたけど？？

![127.0.0.1 - makoto@localhost_~ VT 2021-05-19 22.16.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/483164d8-44a7-ea00-8f47-169cfe37d5d1.png)
これがあかんねん。ここがlocalhostになっていないといけません。

「えっ！？localhostも含まれるんじゃないの！？」

ワイルドカードだから本来は含まれているはずだけど、userの検索順序によって**makoto@localhost**はヒットしない。


###'ユーザー名'@'%'の罠

https://dev.mysql.com/doc/refman/8.0/en/creating-accounts.html

以下、リファレンスより

```sql:ユーザ作成
CREATE USER 'finley'@'localhost'
  IDENTIFIED BY 'password';
GRANT ALL
  ON *.*
  TO 'finley'@'localhost'
  WITH GRANT OPTION;

CREATE USER 'finley'@'%.example.com'
  IDENTIFIED BY 'password';
GRANT ALL
  ON *.*
  TO 'finley'@'%.example.com'
  WITH GRANT OPTION;

CREATE USER 'admin'@'localhost'
  IDENTIFIED BY 'password';
GRANT RELOAD,PROCESS
  ON *.*
  TO 'admin'@'localhost';

CREATE USER 'dummy'@'localhost';
```

>
The 'finley'@'localhost' account is necessary if there is an anonymous-user account for localhost. Without the 'finley'@'localhost' account, that anonymous-user account takes precedence when finley connects from the local host and finley is treated as an anonymous user. The reason for this is that the anonymous-user account has a more specific Host column value than the 'finley'@'%' account and thus comes earlier in the user table sort order. (For information about user table sorting, see Section 6.2.6, “Access Control, Stage 1: Connection Verification”.)

んでここの部分が迷いましたが、こちらのサイトがわかりやすかったです。

[MySQLの匿名ユーザについて](https://www.climb.co.jp/blog_dbmoto/archives/3437)
https://www.climb.co.jp/blog_dbmoto/archives/3437

めっちゃわかりやすかった。

####ポイント
 * ユーザーの検索には順序がある
 * インストールした段階で匿名ユーザーが作成されている

最初に匿名ユーザーが勝手に登録されているのはびっくりですね。

```
select host, user from mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| %         | makoto           |
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |
+-----------+------------------+
5 rows in set (0.00 sec)
```

みたかんじ、''@'localhost'はないけど、あるらしい。見えないだけ？？

mysql.userテーブルを見に行っても、匿名ユーザーは見当たらない。けどあるってことだよね？？

リファレンスの中で、どこにそのような記述があるかは見つけられませんでした。どなたかご存知の方がいましたらコメントにリンク貼ってください！！おねっしゃーす！

んで、''@'localhost'がある前提で話をすすめると、辻褄があう。

###検索の順序

```
mysql> -u makoto -p
```
これでログインしようとしたとき、mysql.userとの照合の順序は次のようになる。

|順序|user|host|
|---|---|---|
|1|makoto|localhost|
|2|匿名|localhost|
|3|makoto|%|

'makoto'@'%'のユーザーは上の表では、３番目のところ。だから、いるはず。

でも、
1のmakoto@localhostではないので、2の'匿名'@localhostを探す。

localhostでアクセスしている場合、'makoto'が'匿名'でヒットしてしまう。

つまり、
**'makoto'@'%' = ''@'localhost'**
という解釈をされてしまう。makotoって匿名ユーザーやんね？って思われてる。

**何回かあったことあるのに、「はじめましてやんね？」って言われてるのと同義。**

んで、匿名ユーザーには権限がない。だからアクセス拒否される。
**初対面やから信頼されていないということと同義。**

###ホストをlocalhostに変更する

```sql
mysql> rename user makoto@% to makoto@localhost;
mysql> select user, host from mysql.user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| makoto           | localhost |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)
```

これでアクセスできるってわけやね！

ま、user登録のときに横着して'%'なんかするからあかんねんけど。