2009-09-10
MySQL 一度DELETEしたuserと同じ名前のuserを登録しようとすると失敗する
うーん。MySQLのバグなんだろうか、一度DELETEしたuserと同じ名前のuserを登録しようとすると失敗する。
やったことはこう。
DELETE 構文で user 'boss' を削除する。
mysql> DELETE FROM mysql.user WHERE user='boss' and host='localhost';
CREATE USER 構文で boss を再度作ろうとしたが、失敗。
mysql> CREATE USER 'boss'@'localhost' IDENTIFIED BY 'password'; ERROR 1396 (HY000): Operation CREATE USER failed for 'boss'@'localhost'
MySQLクイック・リファレンスによると、
本来のユーザ削除はこうらしい。先にREVOKEをやらなかったからいけないのかな?
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'boss'@'localhost'; DELETE FROM mysql.user WHERE user='boss' and host='localhost'; FLUSH PRIVILEGES;
REVOKE 構文を後からやってみたが、REVOKEに失敗する。
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'boss'@'localhost'; ERROR 1269 (HY000): Can't revoke all privileges for one or more of the requested users
困った。
ERROR 1396 (HY000)で検索したら、MySQLのbugレポートに同じ現象が投稿してあった。
http://bugs.mysql.com/bug.php?id=28331
Actually, after more frustrated testing, it seems that the real cause isn't a reserved
word - it seems to be a latent entry in the mysql.db table for a user that has been
removed from the mysql.user table.
mysql.db を調べてみる
SELECT * FROM mysql.db WHERE User='boss' G;
*************************** 1. row ***************************
Host: localhost
Db: boss
User: boss
Select_priv: Y
Insert_priv: Y
Update_priv: Y
Delete_priv: Y
Create_priv: Y
Drop_priv: Y
Grant_priv: N
References_priv: Y
Index_priv: Y
Alter_priv: Y
Create_tmp_table_priv: Y
Lock_tables_priv: Y
Create_view_priv: Y
Show_view_priv: Y
Create_routine_priv: Y
Alter_routine_priv: Y
Execute_priv: Y
1 row in set (0.00 sec)
ERROR:
No query specified
確かに、mysql.db テーブルに boss ユーザが残っている。
同じページの投稿によると、 drop user でユーザ削除を行うとこのbugを回避できるらしい。
やってみる。
mysql> DROP USER boss@localhost; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM mysql.db WHERE User='boss' G; Empty set (0.00 sec) ERROR: No query specified
お、できたかな。
mysql> CREATE USER 'boss'@'localhost' IDENTIFIED BY 'password'; Query OK, 0 rows affected (0.00 sec)
できた。
う〜ん。以前は DELETE 文だけで削除できたような。
MySQLのリファレンスマニュアルを読む
システム管理者は、GRANT コマンドと REVOKE コマンドを使用して、ユーザを作成し、MySQL ユーザに対して次の 4 つのレベルの権限を与えたり取り消すことができます。
- グローバルレベル グローバル権限は特定のサーバ上のすべてのデータベースに適用される。これらの権限は、mysql.user テーブルに保存される。 GRANT ALL ON *.* および REVOKE ALL ON *.* は、グローバル権限の付与および取り消しのみを行う。
- データベースレベル データベース権限は、指定したデータベースのすべてのテーブルに適用される。これらの権限は、mysql.db テーブルおよび mysql.host テーブルに保存される。 GRANT ALL ON db.* および REVOKE ALL ON db.* は、データベース権限の付与および取り消しのみを行う。
- テーブルレベル テーブル権限は、指定したテーブルのすべてのカラムに適用される。これらの権限は、mysql.tables_priv テーブルに保存される。 GRANT ALL ON db.table および REVOKE ALL ON db.table は、テーブル権限の付与および取り消しのみを行う。
- カラムレベル カラム権限は、指定したテーブルの一つのカラムに適用される。これらの権限は、mysql.columns_priv テーブルに保存される。 REVOKE を使用する際は、対象となるカラムを指定することが必要である。
権限を細かく設定すればするほど、使われるテーブルが増えるのか。DELETE FROM mysql.user は当然 user テーブルからしかデータを削除しないけど、CREATE USER と DROP USER 構文は、ちゃんと他のテーブルも見てくれてるんだ。