MySQL 9 min read

MySQLのパスワード変更 ― ALTER USERの書き方と8.4で通らない旧構文

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'; で入れます。