#### 13.7.1.1 ALTER USER Statement

[]()[]()[]()

```
ALTER USER [IF EXISTS]
    user [auth_option] [, user [auth_option]] ...
    [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
    [WITH resource_option [resource_option] ...]
    [password_option | lock_option] ...
    [COMMENT 'comment_string' | ATTRIBUTE 'json_object']

ALTER USER [IF EXISTS]
    USER() user_func_auth_option

ALTER USER [IF EXISTS]
    user [registration_option]

ALTER USER [IF EXISTS]
    USER() [registration_option]

ALTER USER [IF EXISTS]
    user DEFAULT ROLE
    {NONE | ALL | role [, role ] ...}

user:
    (see Section 6.2.4, “Specifying Account Names”)

auth_option: {
    IDENTIFIED BY 'auth_string'
        [REPLACE 'current_auth_string']
        [RETAIN CURRENT PASSWORD]
  | IDENTIFIED BY RANDOM PASSWORD
        [REPLACE 'current_auth_string']
        [RETAIN CURRENT PASSWORD]
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
        [REPLACE 'current_auth_string']
        [RETAIN CURRENT PASSWORD]
  | IDENTIFIED WITH auth_plugin BY RANDOM PASSWORD
        [REPLACE 'current_auth_string']
        [RETAIN CURRENT PASSWORD]
  | IDENTIFIED WITH auth_plugin AS 'auth_string'
  | DISCARD OLD PASSWORD
  | ADD factor factor_auth_option [ADD factor factor_auth_option]
  | MODIFY factor factor_auth_option [MODIFY factor factor_auth_option]
  | DROP factor [DROP factor]
}

user_func_auth_option: {
    IDENTIFIED BY 'auth_string'
        [REPLACE 'current_auth_string']
        [RETAIN CURRENT PASSWORD]
  | DISCARD OLD PASSWORD
}

factor_auth_option: {
    IDENTIFIED BY 'auth_string'
  | IDENTIFIED BY RANDOM PASSWORD
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
  | IDENTIFIED WITH auth_plugin BY RANDOM PASSWORD
  | IDENTIFIED WITH auth_plugin AS 'auth_string'
}

registration_option: {
    factor INITIATE REGISTRATION
  | factor FINISH REGISTRATION SET CHALLENGE_RESPONSE AS 'auth_string'
  | factor UNREGISTER
}

factor: {2 | 3} FACTOR

tls_option: {
   SSL
 | X509
 | CIPHER 'cipher'
 | ISSUER 'issuer'
 | SUBJECT 'subject'
}

resource_option: {
    MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
}

password_option: {
    PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL N DAY]
  | PASSWORD HISTORY {DEFAULT | N}
  | PASSWORD REUSE INTERVAL {DEFAULT | N DAY}
  | PASSWORD REQUIRE CURRENT [DEFAULT | OPTIONAL]
  | FAILED_LOGIN_ATTEMPTS N
  | PASSWORD_LOCK_TIME {N | UNBOUNDED}
}

lock_option: {
    ACCOUNT LOCK
  | ACCOUNT UNLOCK
}
```

 The [`ALTER USER`](alter-user.html) statement modifies MySQL accounts. It enables authentication, role, SSL/TLS, resource-limit, password-management, comment, and attribute properties to be modified for existing accounts. It can also be used to lock and unlock accounts.

 In most cases, [`ALTER USER`](alter-user.html) requires the global [`CREATE USER`](privileges-provided.html#priv_create-user) privilege, or the [`UPDATE`](privileges-provided.html#priv_update) privilege for the `mysql` system schema. The exceptions are:

* Any client who connects to the server using a nonanonymous account can change the password for that account. (In particular, you can change your own password.) To see which account the server authenticated you as, invoke the [`CURRENT_USER()`](information-functions.html#function_current-user) function:

  ```
  SELECT CURRENT_USER();
  ```

* For `DEFAULT ROLE` syntax, [`ALTER USER`](alter-user.html) requires these privileges:

  * Setting the default roles for another user requires the global [`CREATE USER`](privileges-provided.html#priv_create-user) privilege, or the [`UPDATE`](privileges-provided.html#priv_update) privilege for the `mysql.default_roles` system table.

  * Setting the default roles for yourself requires no special privileges, as long as the roles you want as the default have been granted to you.

* Statements that modify secondary passwords require these privileges:

  * The [`APPLICATION_PASSWORD_ADMIN`](privileges-provided.html#priv_application-password-admin) privilege is required to use the `RETAIN CURRENT PASSWORD` or `DISCARD OLD PASSWORD` clause for [`ALTER USER`](alter-user.html) statements that apply to your own account. The privilege is required to manipulate your own secondary password because most users require only one password.

  * If an account is to be permitted to manipulate secondary passwords for all accounts, it requires the [`CREATE USER`](privileges-provided.html#priv_create-user) privilege rather than [`APPLICATION_PASSWORD_ADMIN`](privileges-provided.html#priv_application-password-admin).

 When the [`read_only`](server-system-variables.html#sysvar_read_only) system variable is enabled, [`ALTER USER`](alter-user.html) additionally requires the [`CONNECTION_ADMIN`](privileges-provided.html#priv_connection-admin) privilege (or the deprecated [`SUPER`](privileges-provided.html#priv_super) privilege).

 As of MySQL 8.0.27, these additional privilege considerations apply:

* The [`authentication_policy`](server-system-variables.html#sysvar_authentication_policy) system variable places certain constraints on how the authentication-related clauses of [`ALTER USER`](alter-user.html) statements may be used; for details, see the description of that variable. These constraints do not apply if you have the [`AUTHENTICATION_POLICY_ADMIN`](privileges-provided.html#priv_authentication-policy-admin) privilege.

* To modify an account that uses passwordless authentication, you must have the [`PASSWORDLESS_USER_ADMIN`](privileges-provided.html#priv_passwordless-user-admin) privilege.

 By default, an error occurs if you try to modify a user that does not exist. If the `IF EXISTS` clause is given, the statement produces a warning for each named user that does not exist, rather than an error.

Important

 Under some circumstances, [`ALTER USER`](alter-user.html) may be recorded in server logs or on the client side in a history file such as `~/.mysql_history`, which means that cleartext passwords may be read by anyone having read access to that information. For information about the conditions under which this occurs for the server logs and how to control it, see [Section 6.1.2.3, “Passwords and Logging”](password-logging.html). For similar information about client-side logging, see [Section 4.5.1.3, “mysql Client Logging”](mysql-logging.html).

 There are several aspects to the [`ALTER USER`](alter-user.html) statement, described under the following topics:

* [ALTER USER Overview](alter-user.html#alter-user-overview)

* [ALTER USER Authentication Options](alter-user.html#alter-user-authentication)

* [ALTER USER Multifactor Authentication Options](alter-user.html#alter-user-multifactor-authentication)

* [ALTER USER Registration Options](alter-user.html#alter-user-registration-)

* [ALTER USER Role Options](alter-user.html#alter-user-role)

* [ALTER USER SSL/TLS Options](alter-user.html#alter-user-tls)

* [ALTER USER Resource-Limit Options](alter-user.html#alter-user-resource-limits)

* [ALTER USER Password-Management Options](alter-user.html#alter-user-password-management)

* [ALTER USER Comment and Attribute Options](alter-user.html#alter-user-comments-attributes)

* [ALTER USER Account-Locking Options](alter-user.html#alter-user-account-locking)

* [ALTER USER Binary Logging](alter-user.html#alter-user-binary-logging)

##### ALTER USER Overview

 For each affected account, [`ALTER USER`](alter-user.html) modifies the corresponding row in the `mysql.user` system table to reflect the properties specified in the statement. Unspecified properties retain their current values.

 Each account name uses the format described in [Section 6.2.4, “Specifying Account Names”](account-names.html). The host name part of the account name, if omitted, defaults to `'%'`. It is also possible to specify [`CURRENT_USER`](information-functions.html#function_current-user) or [`CURRENT_USER()`](information-functions.html#function_current-user) to refer to the account associated with the current session.

 For one syntax only, the account may be specified with the [`USER()`](information-functions.html#function_user) function:

```
ALTER USER USER() IDENTIFIED BY 'auth_string';
```

 This syntax enables changing your own password without naming your account literally. (The syntax also supports the `REPLACE`, `RETAIN CURRENT PASSWORD`, and `DISCARD OLD PASSWORD` clauses described at [ALTER USER Authentication Options](alter-user.html#alter-user-authentication).)

 For [`ALTER USER`](alter-user.html) syntax that permits an *`auth_option`* value to follow a *`user`* value, *`auth_option`* indicates how the account authenticates by specifying an account authentication plugin, credentials (for example, a password), or both. Each *`auth_option`* value applies *only* to the account named immediately preceding it.

 Following the *`user`* specifications, the statement may include options for SSL/TLS, resource-limit, password-management, and locking properties. All such options are *global* to the statement and apply to *all* accounts named in the statement.

 Example: Change an account's password and expire it. As a result, the user must connect with the named password and choose a new one at the next connection:

```
ALTER USER 'jeffrey'@'localhost'
  IDENTIFIED BY 'new_password' PASSWORD EXPIRE;
```

 Example: Modify an account to use the `caching_sha2_password` authentication plugin and the given password. Require that a new password be chosen every 180 days, and enable failed-login tracking, such that three consecutive incorrect passwords cause temporary account locking for two days:

```
ALTER USER 'jeffrey'@'localhost'
  IDENTIFIED WITH caching_sha2_password BY 'new_password'
  PASSWORD EXPIRE INTERVAL 180 DAY
  FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 2;
```

 Example: Lock or unlock an account:

```
ALTER USER 'jeffrey'@'localhost' ACCOUNT LOCK;
ALTER USER 'jeffrey'@'localhost' ACCOUNT UNLOCK;
```

 Example: Require an account to connect using SSL and establish a limit of 20 connections per hour:

```
ALTER USER 'jeffrey'@'localhost'
  REQUIRE SSL WITH MAX_CONNECTIONS_PER_HOUR 20;
```

 Example: Alter multiple accounts, specifying some per-account properties and some global properties:

```
ALTER USER
  'jeffrey'@'localhost'
    IDENTIFIED BY 'jeffrey_new_password',
  'jeanne'@'localhost',
  'josh'@'localhost'
    IDENTIFIED BY 'josh_new_password'
    REPLACE 'josh_current_password'
    RETAIN CURRENT PASSWORD
  REQUIRE SSL WITH MAX_USER_CONNECTIONS 2
  PASSWORD HISTORY 5;
```

 The `IDENTIFIED BY` value following `jeffrey` applies only to its immediately preceding account, so it changes the password to `'*`jeffrey_new_password`*'` only for `jeffrey`. For `jeanne`, there is no per-account value (thus leaving the password unchanged). For `josh`, `IDENTIFIED BY` establishes a new password (`'*`josh_new_password`*'`), `REPLACE` is specified to verify that the user issuing the [`ALTER USER`](alter-user.html) statement knows the current password (`'*`josh_current_password`*'`), and that current password is also retained as the account secondary password. (As a result, `josh` can connect with either the primary or secondary password.)

 The remaining properties apply globally to all accounts named in the statement, so for both accounts:

* Connections are required to use SSL.

* The account can be used for a maximum of two simultaneous connections.

* Password changes cannot reuse any of the five most recent passwords.

 Example: Discard the secondary password for `josh`, leaving the account with only its primary password:

```
ALTER USER 'josh'@'localhost' DISCARD OLD PASSWORD;
```

 In the absence of a particular type of option, the account remains unchanged in that respect. For example, with no locking option, the locking state of the account is not changed.

##### ALTER USER Authentication Options

 An account name may be followed by an *`auth_option`* authentication option that specifies the account authentication plugin, credentials, or both. It may also include a password-verification clause that specifies the account current password to be replaced, and clauses that manage whether an account has a secondary password.

Note

 Clauses for random password generation, password verification, and secondary passwords apply only to accounts that use an authentication plugin that stores credentials internally to MySQL. For accounts that use a plugin that performs authentication against a credentials system that is external to MySQL, password management must be handled externally against that system as well. For more information about internal credentials storage, see [Section 6.2.15, “Password Management”](password-management.html).

* *`auth_plugin`* names an authentication plugin. The plugin name can be a quoted string literal or an unquoted name. Plugin names are stored in the `plugin` column of the `mysql.user` system table.

   For *`auth_option`* syntax that does not specify an authentication plugin, the server assigns the default plugin, determined as described in [The Default Authentication Plugin](pluggable-authentication.html#pluggable-authentication-default-plugin). For descriptions of each plugin, see [Section 6.4.1, “Authentication Plugins”](authentication-plugins.html).

* Credentials that are stored internally are stored in the `mysql.user` system table. An `'*`auth_string`*'` value or `RANDOM PASSWORD` specifies account credentials, either as a cleartext (unencrypted) string or hashed in the format expected by the authentication plugin associated with the account, respectively:

  * For syntax that uses `BY '*`auth_string`*'`, the string is cleartext and is passed to the authentication plugin for possible hashing. The result returned by the plugin is stored in the `mysql.user` table. A plugin may use the value as specified, in which case no hashing occurs.

  * For syntax that uses `BY RANDOM PASSWORD`, MySQL generates a random password and as cleartext and passes it to the authentication plugin for possible hashing. The result returned by the plugin is stored in the `mysql.user` table. A plugin may use the value as specified, in which case no hashing occurs.

     Randomly generated passwords are available as of MySQL 8.0.18 and have the characteristics described in [Random Password Generation](password-management.html#random-password-generation).

  * For syntax that uses `AS '*`auth_string`*'`, the string is assumed to be already in the format the authentication plugin requires, and is stored as is in the `mysql.user` table. If a plugin requires a hashed value, the value must be already hashed in a format appropriate for the plugin; otherwise, the value cannot be used by the plugin and correct authentication of client connections does not occur.

     As of MySQL 8.0.17, a hashed string can be either a string literal or a hexadecimal value. The latter corresponds to the type of value displayed by [`SHOW CREATE USER`](show-create-user.html) for password hashes containing unprintable characters when the [`print_identified_with_as_hex`](server-system-variables.html#sysvar_print_identified_with_as_hex) system variable is enabled.

  * If an authentication plugin performs no hashing of the authentication string, the `BY '*`auth_string`*'` and `AS '*`auth_string`*'` clauses have the same effect: The authentication string is stored as is in the `mysql.user` system table.

* The `REPLACE '*`current_auth_string`*'` clause performs password verification and is available as of MySQL 8.0.13. If given:

  * `REPLACE` specifies the account current password to be replaced, as a cleartext (unencrypted) string.

  * The clause must be given if password changes for the are required to specify the current password, as verification that the user attempting to make the change actually knows the current password.

  * The clause is optional if password changes for the account may but need not specify the current password.

  * The statement fails if the clause is given but does not match the current password, even if the clause is optional.

  * `REPLACE` can be specified only when changing the account password for the current user.

   For more information about password verification by specifying the current password, see [Section 6.2.15, “Password Management”](password-management.html).

* The `RETAIN CURRENT PASSWORD` and `DISCARD OLD PASSWORD` clauses implement dual-password capability and are available as of MySQL 8.0.14. Both are optional, but if given, have the following effects:

  * `RETAIN CURRENT PASSWORD` retains an account current password as its secondary password, replacing any existing secondary password. The new password becomes the primary password, but clients can use the account to connect to the server using either the primary or secondary password. (Exception: If the new password specified by the [`ALTER USER`](alter-user.html) statement is empty, the secondary password becomes empty as well, even if `RETAIN CURRENT PASSWORD` is given.)

  * If you specify `RETAIN CURRENT PASSWORD` for an account that has an empty primary password, the statement fails.

  * If an account has a secondary password and you change its primary password without specifying `RETAIN CURRENT PASSWORD`, the secondary password remains unchanged.

  * If you change the authentication plugin assigned to the account, the secondary password is discarded. If you change the authentication plugin and also specify `RETAIN CURRENT PASSWORD`, the statement fails.

  * `DISCARD OLD PASSWORD` discards the secondary password, if one exists. The account retains only its primary password, and clients can use the account to connect to the server only with the primary password.

   For more information about use of dual passwords, see [Section 6.2.15, “Password Management”](password-management.html).

[`ALTER USER`](alter-user.html) permits these *`auth_option`* syntaxes:

* `IDENTIFIED BY '*`auth_string`*' [REPLACE '*`current_auth_string`*'] [RETAIN CURRENT PASSWORD]`

   Sets the account authentication plugin to the default plugin, passes the cleartext `'*`auth_string`*'` value to the plugin for possible hashing, and stores the result in the account row in the `mysql.user` system table.

   The `REPLACE` clause, if given, specifies the account current password, as described previously in this section.

   The `RETAIN CURRENT PASSWORD` clause, if given, causes the account current password to be retained as its secondary password, as described previously in this section.

* `IDENTIFIED BY RANDOM PASSWORD [REPLACE '*`current_auth_string`*'] [RETAIN CURRENT PASSWORD]`

   Sets the account authentication plugin to the default plugin, generates a random password, passes the cleartext password value to the plugin for possible hashing, and stores the result in the account row in the `mysql.user` system table. The statement also returns the cleartext password in a result set to make it available to the user or application executing the statement. For details about the result set and characteristics of randomly generated passwords, see [Random Password Generation](password-management.html#random-password-generation).

   The `REPLACE` clause, if given, specifies the account current password, as described previously in this section.

   The `RETAIN CURRENT PASSWORD` clause, if given, causes the account current password to be retained as its secondary password, as described previously in this section.

* `IDENTIFIED WITH *`auth_plugin`*`

   Sets the account authentication plugin to *`auth_plugin`*, clears the credentials to the empty string (the credentials are associated with the old authentication plugin, not the new one), and stores the result in the account row in the `mysql.user` system table.

   In addition, the password is marked expired. The user must choose a new one when next connecting.

* `IDENTIFIED WITH *`auth_plugin`* BY '*`auth_string`*' [REPLACE '*`current_auth_string`*'] [RETAIN CURRENT PASSWORD]`

   Sets the account authentication plugin to *`auth_plugin`*, passes the cleartext `'*`auth_string`*'` value to the plugin for possible hashing, and stores the result in the account row in the `mysql.user` system table.

   The `REPLACE` clause, if given, specifies the account current password, as described previously in this section.

   The `RETAIN CURRENT PASSWORD` clause, if given, causes the account current password to be retained as its secondary password, as described previously in this section.

* `IDENTIFIED WITH *`auth_plugin`* BY RANDOM PASSWORD [REPLACE '*`current_auth_string`*'] [RETAIN CURRENT PASSWORD]`

   Sets the account authentication plugin to *`auth_plugin`*, generates a random password, passes the cleartext password value to the plugin for possible hashing, and stores the result in the account row in the `mysql.user` system table. The statement also returns the cleartext password in a result set to make it available to the user or application executing the statement. For details about the result set and characteristics of randomly generated passwords, see [Random Password Generation](password-management.html#random-password-generation).

   The `REPLACE` clause, if given, specifies the account current password, as described previously in this section.

   The `RETAIN CURRENT PASSWORD` clause, if given, causes the account current password to be retained as its secondary password, as described previously in this section.

* `IDENTIFIED WITH *`auth_plugin`* AS '*`auth_string`*'`

   Sets the account authentication plugin to *`auth_plugin`* and stores the `'*`auth_string`*'` value as is in the `mysql.user` account row. If the plugin requires a hashed string, the string is assumed to be already hashed in the format the plugin requires.

* `DISCARD OLD PASSWORD`

   Discards the account secondary password, if there is one, as described previously in this section.

 Example: Specify the password as cleartext; the default plugin is used:

```
ALTER USER 'jeffrey'@'localhost'
  IDENTIFIED BY 'password';
```

 Example: Specify the authentication plugin, along with a cleartext password value:

```
ALTER USER 'jeffrey'@'localhost'
  IDENTIFIED WITH mysql_native_password
             BY 'password';
```

 Example: Like the preceding example, but in addition, specify the current password as a cleartext value to satisfy any account requirement that the user making the change knows that password:

```
ALTER USER 'jeffrey'@'localhost'
  IDENTIFIED WITH mysql_native_password
             BY 'password'
             REPLACE 'current_password';
```

 The preceding statement fails unless the current user is `jeffrey` because `REPLACE` is permitted only for changes to the current user's password.

 Example: Establish a new primary password and retain the existing password as the secondary password:

```
ALTER USER 'jeffrey'@'localhost'
  IDENTIFIED BY 'new_password'
  RETAIN CURRENT PASSWORD;
```

 Example: Discard the secondary password, leaving the account with only its primary password:

```
ALTER USER 'jeffery'@'localhost' DISCARD OLD PASSWORD;
```

 Example: Specify the authentication plugin, along with a hashed password value:

```
ALTER USER 'jeffrey'@'localhost'
  IDENTIFIED WITH mysql_native_password
             AS '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
```

 For additional information about setting passwords and authentication plugins, see [Section 6.2.14, “Assigning Account Passwords”](assigning-passwords.html), and [Section 6.2.17, “Pluggable Authentication”](pluggable-authentication.html).

##### ALTER USER Multifactor Authentication Options

 As of MySQL 8.0.27, [`ALTER USER`](alter-user.html) has `ADD`, `MODIFY`, and `DROP` clauses that enable authentication factors to be added, modified, or dropped. In each case, the clause specifies an operation to perform on one authentication factor, and optionally an operation on another authentication factor. For each operation, the *`factor`* item specifies the `FACTOR` keyword preceded by the number 2 or 3 to indicate whether the operation applies to the second or third authentication factor. (1 is not permitted in this context. To act on the first authentication factor, use the syntax described in [ALTER USER Authentication Options](alter-user.html#alter-user-authentication).)

[`ALTER USER`](alter-user.html) multifactor authentication clause constraints are defined by the [`authentication_policy`](server-system-variables.html#sysvar_authentication_policy) system variable. For example, the [`authentication_policy`](server-system-variables.html#sysvar_authentication_policy) setting controls the number of authentication factors that accounts may have, and for each factor, which authentication methods are permitted. See [Configuring the Multifactor Authentication Policy](multifactor-authentication.html#multifactor-authentication-policy).

 When [`ALTER USER`](alter-user.html) adds, modifies, or drops second and third factors in a single statement, operations are executed sequentially, but if any operation in the sequence fails the entire [`ALTER USER`](alter-user.html) statement fails.

 For `ADD`, each named factor must not already exist or it cannot be added. For `MODIFY` and `DROP`, each named factor must exist to be modified or dropped. If a second and third factor are defined, dropping the second factor causes the third factor to take its place as the second factor.

 This statement drops authentication factors 2 and 3, which has the effect of converting the account from 3FA to 1FA:

```
ALTER USER 'user' DROP 2 FACTOR 3 FACTOR;
```

 For additional `ADD`, `MODIFY`, and `DROP` examples, see [Getting Started with Multifactor Authentication](multifactor-authentication.html#multifactor-authentication-getting-started).

 For information about factor-specific rules that determine the default authentication plugin for authentication clauses that do not name a plugin, see [The Default Authentication Plugin](pluggable-authentication.html#pluggable-authentication-default-plugin).

##### ALTER USER Registration Options

 As of MySQL 8.0.27, [`ALTER USER`](alter-user.html) has clauses that enable FIDO devices to be registered and unregistered. For more information, see [Using FIDO Authentication](fido-pluggable-authentication.html#fido-pluggable-authentication-usage), [FIDO Device Unregistration](fido-pluggable-authentication.html#fido-pluggable-authentication-unregistration), and the [**mysql**](mysql.html) client [`--fido-register-factor`](mysql-command-options.html#option_mysql_fido-register-factor) option description.

 The [**mysql**](mysql.html) client [`--fido-register-factor`](mysql-command-options.html#option_mysql_fido-register-factor) option, used for FIDO device registration, causes the [**mysql**](mysql.html) client to generate and execute `INITIATE REGISTRATION` and `FINISH REGISTRATION` statements. These statements are not intended for manual execution.

##### ALTER USER Role Options

[]()

[`ALTER USER ... DEFAULT ROLE`](alter-user.html) defines which roles become active when the user connects to the server and authenticates, or when the user executes the [`SET ROLE DEFAULT`](set-role.html) statement during a session.

[`ALTER USER ... DEFAULT ROLE`](alter-user.html) is alternative syntax for [`SET DEFAULT ROLE`](set-default-role.html) (see [Section 13.7.1.9, “SET DEFAULT ROLE Statement”](set-default-role.html)). However, [`ALTER USER`](alter-user.html) can set the default for only a single user, whereas [`SET DEFAULT ROLE`](set-default-role.html) can set the default for multiple users. On the other hand, you can specify `CURRENT_USER` as the user name for the [`ALTER USER`](alter-user.html) statement, whereas you cannot for [`SET DEFAULT ROLE`](set-default-role.html).

 Each user account name uses the format described previously.

 Each role name uses the format described in [Section 6.2.5, “Specifying Role Names”](role-names.html). For example:

```
ALTER USER 'joe'@'10.0.0.1' DEFAULT ROLE administrator, developer;
```

 The host name part of the role name, if omitted, defaults to `'%'`.

 The clause following the `DEFAULT ROLE` keywords permits these values:

* `NONE`: Set the default to `NONE` (no roles).

* `ALL`: Set the default to all roles granted to the account.

* `*`role`* [, *`role`* ] ...`: Set the default to the named roles, which must exist and be granted to the account at the time [`ALTER USER ... DEFAULT ROLE`](alter-user.html) is executed.

##### ALTER USER SSL/TLS Options

[]()[]()[]()

 MySQL can check X.509 certificate attributes in addition to the usual authentication that is based on the user name and credentials. For background information on the use of SSL/TLS with MySQL, see [Section 6.3, “Using Encrypted Connections”](encrypted-connections.html).

 To specify SSL/TLS-related options for a MySQL account, use a `REQUIRE` clause that specifies one or more *`tls_option`* values.

 Order of `REQUIRE` options does not matter, but no option can be specified twice. The `AND` keyword is optional between `REQUIRE` options.

[`ALTER USER`](alter-user.html) permits these *`tls_option`* values:

* `NONE`

   Indicates that all accounts named by the statement have no SSL or X.509 requirements. Unencrypted connections are permitted if the user name and password are valid. Encrypted connections can be used, at the client's option, if the client has the proper certificate and key files.

  ```
  ALTER USER 'jeffrey'@'localhost' REQUIRE NONE;
  ```

   Clients attempt to establish a secure connection by default. For clients that have `REQUIRE NONE`, the connection attempt falls back to an unencrypted connection if a secure connection cannot be established. To require an encrypted connection, a client need specify only the [`--ssl-mode=REQUIRED`](connection-options.html#option_general_ssl-mode) option; the connection attempt fails if a secure connection cannot be established.

* `SSL`

   Tells the server to permit only encrypted connections for all accounts named by the statement.

  ```
  ALTER USER 'jeffrey'@'localhost' REQUIRE SSL;
  ```

   Clients attempt to establish a secure connection by default. For accounts that have `REQUIRE SSL`, the connection attempt fails if a secure connection cannot be established.

* `X509`

   For all accounts named by the statement, requires that clients present a valid certificate, but the exact certificate, issuer, and subject do not matter. The only requirement is that it should be possible to verify its signature with one of the CA certificates. Use of X.509 certificates always implies encryption, so the `SSL` option is unnecessary in this case.

  ```
  ALTER USER 'jeffrey'@'localhost' REQUIRE X509;
  ```

   For accounts with `REQUIRE X509`, clients must specify the [`--ssl-key`](connection-options.html#option_general_ssl-key) and [`--ssl-cert`](connection-options.html#option_general_ssl-cert) options to connect. (It is recommended but not required that [`--ssl-ca`](connection-options.html#option_general_ssl-ca) also be specified so that the public certificate provided by the server can be verified.) This is true for `ISSUER` and `SUBJECT` as well because those `REQUIRE` options imply the requirements of `X509`.

* `ISSUER '*`issuer`*'`

   For all accounts named by the statement, requires that clients present a valid X.509 certificate issued by CA `'*`issuer`*'`. If a client presents a certificate that is valid but has a different issuer, the server rejects the connection. Use of X.509 certificates always implies encryption, so the `SSL` option is unnecessary in this case.

  ```
  ALTER USER 'jeffrey'@'localhost'
    REQUIRE ISSUER '/C=SE/ST=Stockholm/L=Stockholm/
      O=MySQL/CN=CA/emailAddress=ca@example.com';
  ```

   Because `ISSUER` implies the requirements of `X509`, clients must specify the [`--ssl-key`](connection-options.html#option_general_ssl-key) and [`--ssl-cert`](connection-options.html#option_general_ssl-cert) options to connect. (It is recommended but not required that [`--ssl-ca`](connection-options.html#option_general_ssl-ca) also be specified so that the public certificate provided by the server can be verified.)

* `SUBJECT '*`subject`*'`

   For all accounts named by the statement, requires that clients present a valid X.509 certificate containing the subject *`subject`*. If a client presents a certificate that is valid but has a different subject, the server rejects the connection. Use of X.509 certificates always implies encryption, so the `SSL` option is unnecessary in this case.

  ```
  ALTER USER 'jeffrey'@'localhost'
    REQUIRE SUBJECT '/C=SE/ST=Stockholm/L=Stockholm/
      O=MySQL demo client certificate/
      CN=client/emailAddress=client@example.com';
  ```

   MySQL does a simple string comparison of the `'*`subject`*'` value to the value in the certificate, so lettercase and component ordering must be given exactly as present in the certificate.

   Because `SUBJECT` implies the requirements of `X509`, clients must specify the [`--ssl-key`](connection-options.html#option_general_ssl-key) and [`--ssl-cert`](connection-options.html#option_general_ssl-cert) options to connect. (It is recommended but not required that [`--ssl-ca`](connection-options.html#option_general_ssl-ca) also be specified so that the public certificate provided by the server can be verified.)

* `CIPHER '*`cipher`*'`

   For all accounts named by the statement, requires a specific cipher method for encrypting connections. This option is needed to ensure that ciphers and key lengths of sufficient strength are used. Encryption can be weak if old algorithms using short encryption keys are used.

  ```
  ALTER USER 'jeffrey'@'localhost'
    REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';
  ```

 The `SUBJECT`, `ISSUER`, and `CIPHER` options can be combined in the `REQUIRE` clause:

```
ALTER USER 'jeffrey'@'localhost'
  REQUIRE SUBJECT '/C=SE/ST=Stockholm/L=Stockholm/
    O=MySQL demo client certificate/
    CN=client/emailAddress=client@example.com'
  AND ISSUER '/C=SE/ST=Stockholm/L=Stockholm/
    O=MySQL/CN=CA/emailAddress=ca@example.com'
  AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
```

##### ALTER USER Resource-Limit Options

[]()[]()

 It is possible to place limits on use of server resources by an account, as discussed in [Section 6.2.21, “Setting Account Resource Limits”](user-resources.html). To do so, use a `WITH` clause that specifies one or more *`resource_option`* values.

 Order of `WITH` options does not matter, except that if a given resource limit is specified multiple times, the last instance takes precedence.

[`ALTER USER`](alter-user.html) permits these *`resource_option`* values:

* `MAX_QUERIES_PER_HOUR *`count`*`, `MAX_UPDATES_PER_HOUR *`count`*`, `MAX_CONNECTIONS_PER_HOUR *`count`*`

   For all accounts named by the statement, these options restrict how many queries, updates, and connections to the server are permitted to each account during any given one-hour period. If *`count`* is `0` (the default), this means that there is no limitation for the account.

* `MAX_USER_CONNECTIONS *`count`*`

   For all accounts named by the statement, restricts the maximum number of simultaneous connections to the server by each account. A nonzero *`count`* specifies the limit for the account explicitly. If *`count`* is `0` (the default), the server determines the number of simultaneous connections for the account from the global value of the [`max_user_connections`](server-system-variables.html#sysvar_max_user_connections) system variable. If [`max_user_connections`](server-system-variables.html#sysvar_max_user_connections) is also zero, there is no limit for the account.

 Example:

```
ALTER USER 'jeffrey'@'localhost'
  WITH MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;
```

##### ALTER USER Password-Management Options

[`ALTER USER`](alter-user.html) supports several *`password_option`* values for password management:

* Password expiration options: You can expire an account password manually and establish its password expiration policy. Policy options do not expire the password. Instead, they determine how the server applies automatic expiration to the account based on password age, which is assessed from the date and time of the most recent account password change.

* Password reuse options: You can restrict password reuse based on number of password changes, time elapsed, or both.

* Password verification-required options: You can indicate whether attempts to change an account password must specify the current password, as verification that the user attempting to make the change actually knows the current password.

* Incorrect-password failed-login tracking options: You can cause the server to track failed login attempts and temporarily lock accounts for which too many consecutive incorrect passwords are given. The required number of failures and the lock time are configurable.

 This section describes the syntax for password-management options. For information about establishing policy for password management, see [Section 6.2.15, “Password Management”](password-management.html).

 If multiple password-management options of a given type are specified, the last one takes precedence. For example, `PASSWORD EXPIRE DEFAULT PASSWORD EXPIRE NEVER` is the same as `PASSWORD EXPIRE NEVER`.

Note

 Except for the options that pertain to failed-login tracking, password-management options apply only to accounts that use an authentication plugin that stores credentials internally to MySQL. For accounts that use a plugin that performs authentication against a credentials system that is external to MySQL, password management must be handled externally against that system as well. For more information about internal credentials storage, see [Section 6.2.15, “Password Management”](password-management.html).

 A client has an expired password if the account password was expired manually or the password age is considered greater than its permitted lifetime per the automatic expiration policy. In this case, the server either disconnects the client or restricts the operations permitted to it (see [Section 6.2.16, “Server Handling of Expired Passwords”](expired-password-handling.html)). Operations performed by a restricted client result in an error until the user establishes a new account password.

Note

 Although it is possible to “reset” an expired password by setting it to its current value, it is preferable, as a matter of good policy, to choose a different password. DBAs can enforce non-reuse by establishing an appropriate password-reuse policy. See [Password Reuse Policy](password-management.html#password-reuse-policy).

[`ALTER USER`](alter-user.html) permits these *`password_option`* values for controlling password expiration:

* `PASSWORD EXPIRE`

   Immediately marks the password expired for all accounts named by the statement.

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE;
  ```

* `PASSWORD EXPIRE DEFAULT`

   Sets all accounts named by the statement so that the global expiration policy applies, as specified by the [`default_password_lifetime`](server-system-variables.html#sysvar_default_password_lifetime) system variable.

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE DEFAULT;
  ```

* `PASSWORD EXPIRE NEVER`

   This expiration option overrides the global policy for all accounts named by the statement. For each, it disables password expiration so that the password never expires.

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE NEVER;
  ```

* `PASSWORD EXPIRE INTERVAL *`N`* DAY`

   This expiration option overrides the global policy for all accounts named by the statement. For each, it sets the password lifetime to *`N`* days. The following statement requires the password to be changed every 180 days:

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 180 DAY;
  ```

[`ALTER USER`](alter-user.html) permits these *`password_option`* values for controlling reuse of previous passwords based on required minimum number of password changes:

* `PASSWORD HISTORY DEFAULT`

   Sets all accounts named by the statement so that the global policy about password history length applies, to prohibit reuse of passwords before the number of changes specified by the [`password_history`](server-system-variables.html#sysvar_password_history) system variable.

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD HISTORY DEFAULT;
  ```

* `PASSWORD HISTORY *`N`*`

   This history-length option overrides the global policy for all accounts named by the statement. For each, it sets the password history length to *`N`* passwords, to prohibit reusing any of the *`N`* most recently chosen passwords. The following statement prohibits reuse of any of the previous 6 passwords:

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD HISTORY 6;
  ```

[`ALTER USER`](alter-user.html) permits these *`password_option`* values for controlling reuse of previous passwords based on time elapsed:

* `PASSWORD REUSE INTERVAL DEFAULT`

   Sets all statements named by the account so that the global policy about time elapsed applies, to prohibit reuse of passwords newer than the number of days specified by the [`password_reuse_interval`](server-system-variables.html#sysvar_password_reuse_interval) system variable.

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD REUSE INTERVAL DEFAULT;
  ```

* `PASSWORD REUSE INTERVAL *`N`* DAY`

   This time-elapsed option overrides the global policy for all accounts named by the statement. For each, it sets the password reuse interval to *`N`* days, to prohibit reuse of passwords newer than that many days. The following statement prohibits password reuse for 360 days:

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD REUSE INTERVAL 360 DAY;
  ```

[`ALTER USER`](alter-user.html) permits these *`password_option`* values for controlling whether attempts to change an account password must specify the current password, as verification that the user attempting to make the change actually knows the current password:

* `PASSWORD REQUIRE CURRENT`

   This verification option overrides the global policy for all accounts named by the statement. For each, it requires that password changes specify the current password.

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT;
  ```

* `PASSWORD REQUIRE CURRENT OPTIONAL`

   This verification option overrides the global policy for all accounts named by the statement. For each, it does not require that password changes specify the current password. (The current password may but need not be given.)

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT OPTIONAL;
  ```

* `PASSWORD REQUIRE CURRENT DEFAULT`

   Sets all statements named by the account so that the global policy about password verification applies, as specified by the [`password_require_current`](server-system-variables.html#sysvar_password_require_current) system variable.

  ```
  ALTER USER 'jeffrey'@'localhost' PASSWORD REQUIRE CURRENT DEFAULT;
  ```

 As of MySQL 8.0.19, [`ALTER USER`](alter-user.html) permits these *`password_option`* values for controlling failed-login tracking:

* `FAILED_LOGIN_ATTEMPTS *`N`*`

   Whether to track account login attempts that specify an incorrect password. *`N`* must be a number from 0 to 32767. A value of 0 disables failed-login tracking. Values greater than 0 indicate how many consecutive password failures cause temporary account locking (if `PASSWORD_LOCK_TIME` is also nonzero).

* `PASSWORD_LOCK_TIME {*`N`* | UNBOUNDED}`

   How long to lock the account after too many consecutive login attempts provide an incorrect password. *`N`* must be a number from 0 to 32767, or `UNBOUNDED`. A value of 0 disables temporary account locking. Values greater than 0 indicate how long to lock the account in days. A value of `UNBOUNDED` causes the account locking duration to be unbounded; once locked, the account remains in a locked state until unlocked. For information about the conditions under which unlocking occurs, see [Failed-Login Tracking and Temporary Account Locking](password-management.html#failed-login-tracking).

 For failed-login tracking and temporary locking to occur, an account's `FAILED_LOGIN_ATTEMPTS` and `PASSWORD_LOCK_TIME` options both must be nonzero. The following statement modifies an account such that it remains locked for two days after four consecutive password failures:

```
ALTER USER 'jeffrey'@'localhost'
  FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 2;
```

##### ALTER USER Comment and Attribute Options

[]()[]()

 MySQL 8.0.21 and higher supports user comments and user attributes, as described in [Section 13.7.1.3, “CREATE USER Statement”](create-user.html). These can be modified employing `ALTER USER` by means of the `COMMENT` and `ATTRIBUTE` options, respectively. You cannot specify both options in the same `ALTER USER` statement; attempting to do so results in a syntax error.

 The user comment and user attribute are stored in the [`INFORMATION_SCHEMA.USER_ATTRIBUTES`](information-schema-user-attributes-table.html) table as a JSON object; the user comment is stored as the value for a `comment` key in the ATTRIBUTE column of this table, as shown later in this discussion. The `COMMENT` text can be any arbtitrary quoted text, and replaces any existing user comment. The `ATTRIBUTE` value must be the valid string represntation of a JSON object. This is merged with any existing user attribute as if the [`JSON_MERGE_PATCH()`](json-modification-functions.html#function_json-merge-patch) function had been used on the existing user attribute and the new one; for any keys that are re-used, the new value overwrites the old one, as shown here:

```
mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
    ->     WHERE USER='bill' AND HOST='localhost';
+------+-----------+----------------+
| USER | HOST      | ATTRIBUTE      |
+------+-----------+----------------+
| bill | localhost | {"foo": "bar"} |
+------+-----------+----------------+
1 row in set (0.11 sec)

mysql> ALTER USER 'bill'@'localhost' ATTRIBUTE '{"baz": "faz", "foo": "moo"}';
Query OK, 0 rows affected (0.22 sec)

mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
    ->     WHERE USER='bill' AND HOST='localhost';
+------+-----------+------------------------------+
| USER | HOST      | ATTRIBUTE                    |
+------+-----------+------------------------------+
| bill | localhost | {"baz": "faz", "foo": "moo"} |
+------+-----------+------------------------------+
1 row in set (0.00 sec)
```

 To remove a key and its value from the user attribute, set the key to JSON `null` (must be lowercase and unquoted), like this:

```
mysql> ALTER USER 'bill'@'localhost' ATTRIBUTE '{"foo": null}';
Query OK, 0 rows affected (0.08 sec)

mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
    ->     WHERE USER='bill' AND HOST='localhost';
+------+-----------+----------------+
| USER | HOST      | ATTRIBUTE      |
+------+-----------+----------------+
| bill | localhost | {"baz": "faz"} |
+------+-----------+----------------+
1 row in set (0.00 sec)
```

 To set an existing user comment to an empty string, use `ALTER USER ... COMMENT ''`. This leaves an empty `comment` value in the [`USER_ATTRIBUTES`](information-schema-user-attributes-table.html) table; to remove the user comment completely, use `ALTER USER ... ATTRIBUTE ...` with the value for the column key set to JSON `null` (unquoted, in lower case). This is illustrated by the following sequence of SQL statements:

```
mysql> ALTER USER 'bill'@'localhost' COMMENT 'Something about Bill';
Query OK, 0 rows affected (0.06 sec)

mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
    ->     WHERE USER='bill' AND HOST='localhost';
+------+-----------+---------------------------------------------------+
| USER | HOST      | ATTRIBUTE                                         |
+------+-----------+---------------------------------------------------+
| bill | localhost | {"baz": "faz", "comment": "Something about Bill"} |
+------+-----------+---------------------------------------------------+
1 row in set (0.00 sec)

mysql> ALTER USER 'bill'@'localhost' COMMENT '';
Query OK, 0 rows affected (0.09 sec)

mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
    ->     WHERE USER='bill' AND HOST='localhost';
+------+-----------+-------------------------------+
| USER | HOST      | ATTRIBUTE                     |
+------+-----------+-------------------------------+
| bill | localhost | {"baz": "faz", "comment": ""} |
+------+-----------+-------------------------------+
1 row in set (0.00 sec)

mysql> ALTER USER 'bill'@'localhost' ATTRIBUTE '{"comment": null}';
Query OK, 0 rows affected (0.07 sec)

mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
    ->     WHERE USER='bill' AND HOST='localhost';
+------+-----------+----------------+
| USER | HOST      | ATTRIBUTE      |
+------+-----------+----------------+
| bill | localhost | {"baz": "faz"} |
+------+-----------+----------------+
1 row in set (0.00 sec)
```

##### ALTER USER Account-Locking Options

[]()

 MySQL supports account locking and unlocking using the `ACCOUNT LOCK` and `ACCOUNT UNLOCK` options, which specify the locking state for an account. For additional discussion, see [Section 6.2.20, “Account Locking”](account-locking.html).

 If multiple account-locking options are specified, the last one takes precedence.

 As of MySQL 8.0.19, [`ALTER USER ... UNLOCK`](alter-user.html) unlocks any account named by the statement that is temporarily locked due to too many failed logins. See [Section 6.2.15, “Password Management”](password-management.html).

##### ALTER USER Binary Logging

[]()

[`ALTER USER`](alter-user.html) is written to the binary log if it succeeds, but not if it fails; in that case, rollback occurs and no changes are made. A statement written to the binary log includes all named users. If the `IF EXISTS` clause is given, this includes even users that do not exist and were not altered.

 If the original statement changes the credentials for a user, the statement written to the binary log specifies the applicable authentication plugin for that user, determined as follows:

* The plugin named in the original statement, if one was specified.

* Otherwise, the plugin associated with the user account if the user exists, or the default authentication plugin if the user does not exist. (If the statement written to the binary log must specify a particular authentication plugin for a user, include it in the original statement.)

 If the server adds the default authentication plugin for any users in the statement written to the binary log, it writes a warning to the error log naming those users.

 If the original statement specifies the `FAILED_LOGIN_ATTEMPTS` or `PASSWORD_LOCK_TIME` option, the statement written to the binary log includes the option.

[`ALTER USER`](alter-user.html) statements with clauses that support multifactor authentication (MFA) are written to the binary log with the exception of `ALTER USER *`user factor`* INITIATE REGISTRATION` statements.

* `ALTER USER *`user factor`* FINISH REGISTRATION SET CHALLENGE_RESPONSE AS '*`auth_string`*'` statements are written to the binary log as `ALTER USER *`user`* MODIFY *`factor`* IDENTIFIED WITH authentication_fido AS *`fido_hash_string`*`;

* In a replication context, the replication user requires [`PASSWORDLESS_USER_ADMIN`](privileges-provided.html#priv_passwordless-user-admin) privilege to execute `ALTER USER ... MODIFY` operations on accounts configured for passwordless authentication using the `authentication_fido` plugin.

