MySQL 8.4 でパスワードを変えるには ALTER USER を使います。古い記事にある PASSWORD() 関数を使う書き方は通りません。この記事の出力は MySQL 8.4.6 で採りました。
まず見る(結論)
- 他人のパスワード:
ALTER USER 'app'@'%' IDENTIFIED BY '新しいパスワード'; - 自分のパスワード:
ALTER USER USER() IDENTIFIED BY '...';かSET PASSWORD = '...'; - 変更はすぐ効く。
FLUSH PRIVILEGESは要らない - アプリケーションの切り替え中に止めたくないなら
RETAIN CURRENT PASSWORDで新旧を両方有効にできる
ALTER USER で変える
アカウントは「ユーザー名@host」で指定します。'app'@'%' と 'app'@'localhost' は別のアカウントなので、変えたい方を正確に書きます(一覧は SELECT user, host FROM mysql.user;)。
mysql> ALTER USER 'app'@'%' IDENTIFIED BY '******';
Query OK, 0 rows affected
変更後、新しいパスワードではすぐ接続でき、古いパスワードでは拒否されました。FLUSH PRIVILEGES は打っていません。
$ mysql -h 127.0.0.1 -u app -p # 古いパスワードを入力
ERROR 1045 (28000): Access denied for user 'app'@'127.0.0.1' (using password: YES)
FLUSH PRIVILEGES が必要なのは、mysql.user などの表を UPDATE で直接書き換えたときです。
SET PASSWORD でも変えられる
mysql> SET PASSWORD FOR 'app'@'%' = '******'; -- 他人(管理者)
mysql> SET PASSWORD = '******'; -- 自分
どちらも通り、変えたパスワードで接続できました。一般ユーザーが自分のパスワードを変えるのに、特別な権限は要りません。
8.4 で通らない書き方
PASSWORD() 関数
5.7 以前の記事によくある書き方は、構文エラーになります。PASSWORD() 関数は 8.0 で削除されています。
mysql> SET PASSWORD FOR 'app'@'%' = PASSWORD('******');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PASSWORD('******')' at line 1
PASSWORD(...) の部分を外し、文字列をそのまま書けば通ります。
mysql_native_password
古いクライアントに合わせて mysql_native_password で作ろうとすると、エラーになります。
mysql> CREATE USER 'old'@'%' IDENTIFIED WITH mysql_native_password BY '******';
ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded
mysql> SELECT plugin_name, plugin_status FROM information_schema.plugins
-> WHERE plugin_name LIKE '%native%';
+-----------------------+---------------+
| plugin_name | plugin_status |
+-----------------------+---------------+
| mysql_native_password | DISABLED |
+-----------------------+---------------+
8.4 では既定で無効です。サーバーの起動オプション --mysql-native-password=ON で有効にできますが、まずはクライアントを既定の caching_sha2_password に対応した版に上げることを考えます。
他人のパスワードは管理者しか変えられない
一般ユーザーが別のアカウントを ALTER USER すると、権限エラーになります。
ERROR 1227 (42000): Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation
止めずに切り替える(RETAIN CURRENT PASSWORD)
複数のアプリケーションサーバーが同じアカウントで接続していると、パスワードを変えた時点で、設定を変えていないサーバーが接続できなくなります。RETAIN CURRENT PASSWORD を付けると、古いパスワードを残したまま新しいパスワードを設定できます。
mysql> ALTER USER 'app'@'%' IDENTIFIED BY '新しい値' RETAIN CURRENT PASSWORD;
この状態では、新しいパスワードでも古いパスワードでも接続できました。全部のサーバーの設定を変え終えたら、古いパスワードを捨てます。
mysql> ALTER USER 'app'@'%' DISCARD OLD PASSWORD;
この後、古いパスワードでは ERROR 1045 になり、新しいパスワードだけが使えました。
期限切れにして次のログインで変えさせる
mysql> ALTER USER 'app'@'%' PASSWORD EXPIRE;
期限切れのアカウントで mysql -e のように対話なしで接続しようとすると、次のメッセージで止まります。
Please use --connect-expired-password option or invoke mysql in interactive mode.
--connect-expired-password を付ければ接続はできますが、パスワードを変えるまで普通の SQL は実行できません。
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
そのユーザー自身が ALTER USER USER() IDENTIFIED BY '...'; で新しいパスワードを設定すると解除されます。
パスワードの強さの検査
公式コンテナイメージの 8.4.6 では、mysql.component は空で、SHOW VARIABLES LIKE 'validate_password%'; も何も返しませんでした。パスワードの長さや複雑さの検査(validate_password コンポーネント)は入っていないので、短いパスワードでも設定できてしまいます。検査が必要なら INSTALL COMPONENT 'file://component_validate_password'; で入れます。