MySQL

MySQLの罠?ユーザー名指定しても匿名ユーザーログインになる

問題

久しぶりにMySQLをインストールしたときのことです。

インストールが終わりadminユーザーを作りました。(※説明の都合上、パスワードをかけていません。)
GRANT ALL PRIVILEGES ON *.* TO admin@'%' WITH GRANT OPTION;

ログイン後、データベースを作ろうとしたときです。

mysql -u admin
CREATE DATABASE `sample` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;

ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'sample'

あれ?
全権限与えたはずなのに??
ユーザー''@'localhost'??
adminで入ったよね???

adminユーザーちゃんと作れてなかったのかな?ってことで確認

rootアカウントで
mysql> SELECT Host, User, Password FROM mysql.user;
+-----------------------+-------+----------+
| Host                  | User  | Password |
+-----------------------+-------+----------+
| localhost             | root  |          |
| localhost.localdomain | root  |          |
| 127.0.0.1             | root  |          |
| ::1                   | root  |          |
| localhost             |       |          |
| localhost.localdomain |       |          |
| %                     | admin |          |
+-----------------------+-------+----------+

ありますねー。
なんでだろー。

・・・

原因

ログインで指定した情報と合致するアカウントが複数ある場合、ユーザー名よりホスト名の具体性が高いアカウントが優先して選択されるようです。

今回の場合、mysql -u adminの候補に ''@'localhost''admin'@'%'があり、ホストの具体性が
'localhost'(リテラル) > '%'(任意のホスト。最も具体性が低い) だったのでadminアカウントで入れていなかった。
ということになります。

同じ権限の 'admin'@'localhost' を追加するか、匿名ユーザーのアカウントを消せば解決しました。

参考

くわしく知りたい方はリンク先の公式リファレンス読んでね。

6.3.2 ユーザーアカウントの追加

localhost アカウントがない場合は、monty がローカルホストから接続する際に、mysql_install_db で作成された localhost の匿名ユーザーアカウントが優先されます。
その結果、monty は匿名ユーザーとして処理されます。その理由は、匿名ユーザーアカウントが 'monty'@'%' アカウントよりも固有の Host カラム値を持っているため、
user テーブルのソート順でより早く表示されるためです。(user テーブルのソートについては、セクション6.2.4「アクセス制御、ステージ 1: 接続の検証」で説明されています。)

6.2.4 アクセス制御、ステージ 1: 接続の検証

サーバーは、具体性がもっとも高い Host 値が先になるように行を並べるソートルールを使用します。リテラルのホスト名および IP アドレスは具体性がもっとも高くなります。
パターン '%' は「任意のホスト」を意味するため、具体性はもっとも低くなります。
空の文字列 '' も「任意のホスト」を意味しますが、'%' のあとにソートされます。
同じ Host 値を持つ行は、もっとも具体的な User 値が最初になるよう並べられます (ブランクの User 値は 「任意のユーザー」を意味し、具体性がもっとも低くなります)。