【MySQL】あるはずの権限が使えない場合はログインアカウントを確認する

先日MySQLにログインしたとき、付与されているはずの権限がなくクエリを投げられなかったことがある。ユーザ名は確かに合っていたのだが、問題はログイン元のホストにあった。

MySQLのユーザに権限を付与するとき、以下のようにユーザ名だけではなくホストも指定する。

GRANT SELECT, INSERT, UPDATE, DELETE ON db.test TO 'udomomo'@'10.254.0.0/255.255.240.0';

すなわち、ユーザ名は同じでも異なるホストからのログインに対して、異なる権限を設定することもできる。(権限付与の際にホストを指定しない場合、任意のホストとみなされる)

GRANT SELECT ON db.test TO 'udomomo';

このようなことができる理由は、mysqlではユーザ名とホスト名を含めて1つの固有なアカウントとみなしているため。 mysql.user テーブルを確認すると、 'udomomo'@'10.254.0.0/255.255.240.0''udomomo'@'%' は異なるアカウントとして記録されている。

SELECT user, host FROM mysql.user where user="udomomo";
+----------+---------------------------+
| user      | host               |
+----------+---------------------------+
| udomomo | %                   |
| udomomo | 10.254.0.0/255.255.240.0  |
+----------+---------------------------+
2 rows in set (0.00 sec)

ではユーザ名 udomomo でログインすると、どちらのアカウントに該当するのだろうか。MySQLでは、ユーザ名のみで複数のアカウントに合致するときは、ホスト名の具体性が高い順に行をソートし、その順番にホストがマッチするか確認する。具体性とは % のようなワイルドカード指定が使われていないものほど先に来るという意味である。すなわち、例えば10.254.0.1からユーザ名 udomomo でログインすれば、必ず 'udomomo'@'10.254.0.0/255.255.240.0' の方にマッチする。

dev.mysql.com

今回の場合、間違って 10.254.0.0/255.255.240.0 に含まれないホストから udomomo でログインしたことで、 INSERT を行うことができなかった(当然パスワードは全く違う文字列なのだが、パスワードマネージャーを使っているため気づかなかった)。 このような時は、今ログインしているアカウントを確認するのが速い。 SELECT CURRENT_USER(); とすれば、今ログインしているアカウントがユーザ名・ホストともに表示される。

SELECT CURRENT_USER();
+--------------------------------+
| CURRENT_USER()                 |
+--------------------------------+
| udomomo@10.254.0.0/255.255.240.0 |
+--------------------------------+
1 row in set (0.01 sec)