※この記事にはアフィリエイト広告(プロモーション)が含まれます。
MySQL では、ユーザーを作る CREATE USER と、権限を付ける GRANT を別々に実行します。作っただけのユーザーはログインできますが、どのデータベースも触れません。この記事の出力は MySQL 8.4.11(Ubuntu 26.04 の標準パッケージ)で採りました。
まず見る(結論)
CREATE USER 'app1'@'localhost' IDENTIFIED BY 'パスワード';
GRANT ALL PRIVILEGES ON appdb.* TO 'app1'@'localhost';
SHOW GRANTS FOR 'app1'@'localhost';
- アカウントは「ユーザー名@host」の組。
'app1'@'localhost'と'app1'@'%'は別のユーザー GRANT ... IDENTIFIED BYは MySQL 8.0 で廃止され、ERROR 1064 になる- まだ無いユーザーに GRANT すると ERROR 1410。先に
CREATE USER - GRANT の後の
FLUSH PRIVILEGESは要らない
ユーザーを作る
mysql> CREATE USER 'app1'@'localhost' IDENTIFIED BY 'Passw0rd!1';
mysql> CREATE USER app2 IDENTIFIED BY 'Passw0rd!2';
mysql> SELECT user, host, plugin FROM mysql.user WHERE user LIKE 'app%';
+------+-----------+-----------------------+
| user | host | plugin |
+------+-----------+-----------------------+
| app1 | localhost | caching_sha2_password |
| app2 | % | caching_sha2_password |
+------+-----------+-----------------------+
host を省くと '%'(どこからでも)になります。'localhost' は同じサーバー上からの接続だけです。別のマシンのアプリから接続するユーザーは、接続元に合わせた host で作ります(外部から接続できないときの記事)。
同じアカウントをもう一度作ると ERROR 1396 (HY000): Operation CREATE USER failed for 'app1'@'localhost' になります。既にあっても止めたくないときは CREATE USER IF NOT EXISTS にします。
Ubuntu の標準パッケージでは、パスワードの強度を検査する validate_password コンポーネントが入っておらず、'abc' のような短いパスワードでも作れました(SHOW VARIABLES LIKE 'validate_password%' が0行)。
権限を付ける
作った直後の権限は USAGE(ログインできるだけ)です。
mysql> SHOW GRANTS FOR 'app1'@'localhost';
+------------------------------------------+
| Grants for app1@localhost |
+------------------------------------------+
| GRANT USAGE ON *.* TO `app1`@`localhost` |
+------------------------------------------+
この状態で app1 としてログインすると、SHOW DATABASES に出るのは information_schema と performance_schema だけです。データベースを使おうとすると次のエラーになります。
USE fsv;
ERROR 1044 (42000): Access denied for user 'app1'@'localhost' to database 'fsv'
SELECT * FROM fsv.t_size LIMIT 1;
ERROR 1142 (42000): SELECT command denied to user 'app1'@'localhost' for table 't_size'
権限は GRANT 権限 ON 対象 TO アカウント で付けます。
| 付けたい範囲 | 書き方 |
|---|---|
| 1つのデータベースの全権限 | GRANT ALL PRIVILEGES ON fsv.* TO 'app1'@'localhost'; |
| 読み取りだけ | GRANT SELECT ON fsv.* TO 'ro'@'%'; |
| 1つの表の読み書き | GRANT SELECT, INSERT, UPDATE, DELETE ON fsv.t_size TO 'app3'@'localhost'; |
| 全データベースの全権限(管理者) | GRANT ALL ON *.* TO 'adm1'@'localhost' WITH GRANT OPTION; |
GRANT はすぐに効きます。app3 に fsv2 の SELECT を付けた直後、FLUSH PRIVILEGES をせずに app3 で USE fsv2 が通りました。FLUSH PRIVILEGES が要るのは mysql.user などの表を INSERT や UPDATE で直接書き換えたときです。
表単位で SELECT・INSERT・UPDATE・DELETE だけを付けた app3 は、その表を DROP TABLE しようとすると ERROR 1142 (42000): DROP command denied になります。アプリ用のユーザーにはこの4つだけを付け、表の作り変えは別のユーザーで行う、という分け方ができます。
8.0 以降で通らない書き方
MySQL 5.7 までの手順書にある、GRANT でユーザー作成とパスワード設定を一度にやる書き方は通りません。
mysql> GRANT ALL ON fsv.* TO 'app4'@'localhost' IDENTIFIED BY 'Passw0rd!4';
ERROR 1064 (42000): You have an error in your SQL syntax; ... near 'IDENTIFIED BY 'Passw0rd!4'' at line 1
mysql> GRANT ALL ON fsv.* TO 'app4'@'localhost';
ERROR 1410 (42000): You are not allowed to create a user with GRANT
ERROR 1410 は「GRANT の宛先のアカウントが存在しない」という意味です。'app1'@'localhost' しか無いのに 'app1'@'127.0.0.1' や app1(='app1'@'%')に GRANT した場合も、同じ ERROR 1410 になりました。
パスワードを変える SET PASSWORD ... = PASSWORD('x') も ERROR 1064 になります。ALTER USER を使います(パスワード変更の記事)。
存在しないデータベースへの GRANT はエラーにならず、GRANT ALL PRIVILEGES ON `nosuchdb`.* が SHOW GRANTS に残りました。データベース名の綴りを間違えても気づけないので、GRANT の後に SHOW GRANTS で確かめます。
権限を外す・ユーザーを消す
REVOKE ALL PRIVILEGES ON fsv.* FROM 'app1'@'localhost';
DROP USER 'app1'@'localhost';
付いていない権限を REVOKE すると ERROR 1141 (42000): There is no such grant defined for user 'app1' on host 'localhost' になります。DROP USER で host を省くと '%' を消します。無いアカウントを消すと ERROR 1396 で、DROP USER IF EXISTS ならエラーになりません。
WITH GRANT OPTION
WITH GRANT OPTION を付けると、そのユーザーが自分の持つ権限を他のユーザーに付けられるようになります。fsv の SELECT だけを WITH GRANT OPTION 付きで持つ app1 は、app3 に SELECT を付けられましたが、INSERT を付けようとすると ERROR 1044 になりました。自分が持っていない権限は渡せません。
関連: MySQLでユーザー一覧を表示する / MySQLのパスワード変更 / MySQLに外部から接続できない / PostgreSQLのユーザー作成