Menu:
account-activity-auditing:: SQL-Based Account Activity Auditing
MySQL enables the creation of accounts that permit client users to connect to the server and access data managed by the server. The primary function of the MySQL privilege system is to authenticate a user who connects from a given host and to associate that user with privileges on a database such as note 'SELECT': select, note 'INSERT': insert, note 'UPDATE': update, and note 'DELETE': delete. Additional functionality includes the ability to grant privileges for administrative operations.
To control which users can connect, each account can be assigned authentication credentials such as a password. The user interface to MySQL accounts consists of SQL statements such as note 'CREATE USER': create-user, note 'GRANT': grant, and note 'REVOKE': revoke. See note account-management-statements::.
The MySQL privilege system ensures that all users may perform only the operations permitted to them. As a user, when you connect to a MySQL server, your identity is determined by the host from which you connect and the user name you specify. When you issue requests after connecting, the system grants privileges according to your identity and what you want to do.
MySQL considers both your host name and user name in identifying you because there is no reason to assume that a given user name belongs to the same person on all hosts. For example, the user 'joe' who connects from 'office.example.com' need not be the same person as the user 'joe' who connects from 'home.example.com'. MySQL handles this by enabling you to distinguish users on different hosts that happen to have the same name: You can grant one set of privileges for connections by 'joe' from 'office.example.com', and a different set of privileges for connections by 'joe' from 'home.example.com'. To see what privileges a given account has, use the *note 'SHOW GRANTS': show-grants. statement. For example:
SHOW GRANTS FOR 'joe'@'office.example.com';
SHOW GRANTS FOR 'joe'@'home.example.com';
Internally, the server stores privilege information in the grant tables of the 'mysql' system database. The MySQL server reads the contents of these tables into memory when it starts and bases access-control decisions on the in-memory copies of the grant tables.
MySQL access control involves two stages when you run a client program that connects to the server:
Stage 1: The server accepts or rejects the connection based on your identity and whether you can verify your identity by supplying the correct password.
Stage 2: Assuming that you can connect, the server checks each statement you issue to determine whether you have sufficient privileges to perform it. For example, if you try to select rows from a table in a database or drop a table from the database, the server verifies that you have the 'SELECT' privilege for the table or the 'DROP' privilege for the database.
For a more detailed description of what happens during each stage, see note connection-access::, and note request-access::. For help in diagnosing privilege-related problems, see *note problems-connecting::.
If your privileges are changed (either by yourself or someone else) while you are connected, those changes do not necessarily take effect immediately for the next statement that you issue. For details about the conditions under which the server reloads the grant tables, see *note privilege-changes::.
There are some things that you cannot do with the MySQL privilege system:
You cannot explicitly specify that a given user should be denied access. That is, you cannot explicitly match a user and then refuse the connection.
You cannot specify that a user has privileges to create or drop tables in a database but not to create or drop the database itself.
A password applies globally to an account. You cannot associate a password with a specific object such as a database, table, or routine.
File: manual.info.tmp, Node: user-names, Next: privileges-provided, Prev: access-control, Up: access-control
MySQL stores accounts in the 'user' table of the 'mysql' system database. An account is defined in terms of a user name and the client host or hosts from which the user can connect to the server. For information about account representation in the 'user' table, see *note grant-tables::.
An account may also have authentication credentials such as a password. The credentials are handled by the account authentication plugin. MySQL supports multiple authentication plugins. Some of them use built-in authentication methods, whereas others enable authentication using external authentication methods. See *note pluggable-authentication::.
There are several distinctions between the way user names and passwords are used by MySQL and your operating system:
User names, as used by MySQL for authentication purposes, have nothing to do with user names (login names) as used by Windows or Unix. On Unix, most MySQL clients by default try to log in using the current Unix user name as the MySQL user name, but that is for convenience only. The default can be overridden easily, because client programs permit any user name to be specified with a '-u' or '--user' option. This means that anyone can attempt to connect to the server using any user name, so you cannot make a database secure in any way unless all MySQL accounts have passwords. Anyone who specifies a user name for an account that has no password can connect successfully to the server.
MySQL user names are up to 32 characters long. Operating system user names may have a different maximum length.
Warning:
The MySQL user name length limit is hardcoded in MySQL servers and clients, and trying to circumvent it by modifying the definitions of the tables in the 'mysql' database does not work.
You should never alter the structure of tables in the 'mysql' database in any manner whatsoever except by means of the procedure that is described in *note upgrading::. Attempting to redefine the MySQL system tables in any other fashion results in undefined and unsupported behavior. The server is free to ignore rows that become malformed as a result of such modifications.
To authenticate client connections for accounts that use built-in authentication methods, the server uses passwords stored in the 'user' table. These passwords are distinct from passwords for logging in to your operating system. There is no necessary connection between the 'external' password you use to log in to a Windows or Unix machine and the password you use to access the MySQL server on that machine.
If the server authenticates a client using some other plugin, the authentication method that the plugin implements may or may not use a password stored in the 'user' table. In this case, it is possible that an external password is also used to authenticate to the MySQL server.
Passwords stored in the 'user' table are encrypted using plugin-specific algorithms. For information about MySQL native password hashing, see *note password-hashing::.
If the user name and password contain only ASCII characters, it is possible to connect to the server regardless of character set settings. To enable connections when the user name or password contain non-ASCII characters, client applications should call the 'mysql_options()' (https://dev.mysql.com/doc/c-api/5.7/en/mysql-options.html) C API function with the 'MYSQL_SET_CHARSET_NAME' option and appropriate character set name as arguments. This causes authentication to take place using the specified character set. Otherwise, authentication fails unless the server default character set is the same as the encoding in the authentication defaults.
Standard MySQL client programs support a '--default-character-set' option that causes 'mysql_options()' (https://dev.mysql.com/doc/c-api/5.7/en/mysql-options.html) to be called as just described. In addition, character set autodetection is supported as described in *note charset-connection::. For programs that use a connector that is not based on the C API, the connector may provide an equivalent to 'mysql_options()' (https://dev.mysql.com/doc/c-api/5.7/en/mysql-options.html) that can be used instead. Check the connector documentation.
The preceding notes do not apply for 'ucs2', 'utf16', and 'utf32', which are not permitted as client character sets.
The MySQL installation process populates the grant tables with an initial 'root' account, as described in note default-privileges::, which also discusses how to assign a password to it. Thereafter, you normally set up, modify, and remove MySQL accounts using statements such as note 'CREATE USER': create-user, note 'DROP USER': drop-user, note 'GRANT': grant, and note 'REVOKE': revoke. See note creating-accounts::, and *note account-management-statements::.
To connect to a MySQL server with a command-line client, specify user name and password options as necessary for the account that you want to use:
$> mysql --user=finley --password DB_NAME
If you prefer short options, the command looks like this:
$> mysql -u finley -p DB_NAME
If you omit the password value following the '--password' or '-p' option on the command line (as just shown), the client prompts for one. Alternatively, the password can be specified on the command line:
$> mysql --user=finley --password=PASSWORD DB_NAME
$> mysql -u finley -pPASSWORD DB_NAME
If you use the '-p' option, there must be no space between '-p' and the following password value.
Specifying a password on the command line should be considered insecure. See note password-security-user::. To avoid giving the password on the command line, use an option file or a login path file. See note option-files::, and *note mysql-config-editor::.
For additional information about specifying user names, passwords, and other connection parameters, see *note connecting::.
File: manual.info.tmp, Node: privileges-provided, Next: grant-tables, Prev: user-names, Up: access-control
The privileges granted to a MySQL account determine which operations the account can perform. MySQL privileges differ in the contexts in which they apply and at different levels of operation:
Administrative privileges enable users to manage operation of the MySQL server. These privileges are global because they are not specific to a particular database.
Database privileges apply to a database and to all objects within it. These privileges can be granted for specific databases, or globally so that they apply to all databases.
Privileges for database objects such as tables, indexes, views, and stored routines can be granted for specific objects within a database, for all objects of a given type within a database (for example, all tables in a database), or globally for all objects of a given type in all databases.
Information about account privileges is stored in the grant tables in the 'mysql' system database. For a description of the structure and contents of these tables, see note grant-tables::. The MySQL server reads the contents of the grant tables into memory when it starts, and reloads them under the circumstances indicated in note privilege-changes::. The server bases access-control decisions on the in-memory copies of the grant tables.
Important:
Some MySQL releases introduce changes to the grant tables to add new privileges or features. To make sure that you can take advantage of any new capabilities, update your grant tables to the current structure whenever you upgrade MySQL. See *note upgrading::.
The following sections summarize the available privileges, provide more detailed descriptions of each privilege, and offer usage guidelines.
*note privileges-provided-summary::
*note privileges-provided-static::
*note privileges-provided-guidelines::
Summary of Available Privileges
The following table shows the privilege names used in note 'GRANT': grant. and note 'REVOKE': revoke. statements, along with the column name associated with each privilege in the grant tables and the context in which the privilege applies.
Permissible Privileges for GRANT and REVOKE
Privilege Grant Table Column Context
'ALL [PRIVILEGES]'
Synonym for 'all Server administration privileges'
'ALTER'
'Alter_priv' Tables
'ALTER ROUTINE'
'Alter_routine_priv' Stored routines
'CREATE'
'Create_priv' Databases, tables, or indexes
'CREATE ROUTINE'
'Create_routine_priv' Stored routines
'CREATE TABLESPACE'
'Create_tablespace_priv'Server administration
'CREATE TEMPORARY TABLES'
'Create_tmp_table_priv'Tables
'CREATE USER'
'Create_user_priv' Server administration
'CREATE VIEW'
'Create_view_priv' Views
'DELETE'
'Delete_priv' Tables
'DROP'
'Drop_priv' Databases, tables, or views
'EVENT'
'Event_priv' Databases
'EXECUTE'
'Execute_priv' Stored routines
'FILE'
'File_priv' File access on server host
'GRANT OPTION'
'Grant_priv' Databases, tables, or stored routines
'INDEX'
'Index_priv' Tables
'INSERT'
'Insert_priv' Tables or columns
'LOCK TABLES'
'Lock_tables_priv' Databases
'PROCESS'
'Process_priv' Server administration
'PROXY'
See 'proxies_priv' Server administration table
'REFERENCES'
'References_priv' Databases or tables
'RELOAD'
'Reload_priv' Server administration
'REPLICATION CLIENT'
'Repl_client_priv' Server administration
'REPLICATION SLAVE'
'Repl_slave_priv' Server administration
'SELECT'
'Select_priv' Tables or columns
'SHOW DATABASES'
'Show_db_priv' Server administration
'SHOW VIEW'
'Show_view_priv' Views
'SHUTDOWN'
'Shutdown_priv' Server administration
'SUPER'
'Super_priv' Server administration
'TRIGGER'
'Trigger_priv' Tables
'UPDATE'
'Update_priv' Tables or columns
'USAGE'
Synonym for 'no Server administration privileges'
Privilege Descriptions
The following list provides general descriptions of each privilege available in MySQL. Particular SQL statements might have more specific privilege requirements than indicated here. If so, the description for the statement in question provides the details.
'ALL', 'ALL PRIVILEGES'
These privilege specifiers are shorthand for 'all privileges available at a given privilege level' (except 'GRANT OPTION'). For example, granting 'ALL' at the global or table level grants all global privileges or all table-level privileges, respectively.
'ALTER'
Enables use of the note 'ALTER TABLE': alter-table. statement to change the structure of tables. note 'ALTER TABLE': alter-table. also requires the 'CREATE' and 'INSERT' privileges. Renaming a table requires 'ALTER' and 'DROP' on the old table, 'CREATE', and 'INSERT' on the new table.
'ALTER ROUTINE'
Enables use of statements that alter or drop stored routines (stored procedures and functions).
'CREATE'
Enables use of statements that create new databases and tables.
'CREATE ROUTINE'
Enables use of statements that create stored routines (stored procedures and functions).
'CREATE TABLESPACE'
Enables use of statements that create, alter, or drop tablespaces and log file groups.
'CREATE TEMPORARY TABLES'
Enables the creation of temporary tables using the *note 'CREATE TEMPORARY TABLE': create-temporary-table. statement.
After a session has created a temporary table, the server performs no further privilege checks on the table. The creating session can perform any operation on the table, such as note 'DROP TABLE': drop-table, note 'INSERT': insert, note 'UPDATE': update, or note 'SELECT': select. For more information, see *note create-temporary-table::.
'CREATE USER'
Enables use of the note 'ALTER USER': alter-user, note 'CREATE USER': create-user, note 'DROP USER': drop-user, note 'RENAME USER': rename-user, and *note 'REVOKE ALL PRIVILEGES': revoke. statements.
'CREATE VIEW'
Enables use of the *note 'CREATE VIEW': create-view. statement.
'DELETE'
Enables rows to be deleted from tables in a database.
'DROP'
Enables use of statements that drop (remove) existing databases, tables, and views. The 'DROP' privilege is required to use the 'ALTER TABLE ... DROP PARTITION' statement on a partitioned table. The 'DROP' privilege is also required for *note 'TRUNCATE TABLE': truncate-table.
'EVENT'
Enables use of statements that create, alter, drop, or display events for the Event Scheduler.
'EXECUTE'
Enables use of statements that execute stored routines (stored procedures and functions).
'FILE'
Affects the following operations and server behaviors:
* Enables reading and writing files on the server host using the
*note 'LOAD DATA': load-data. and *note 'SELECT ... INTO
OUTFILE': select-into. statements and the 'LOAD_FILE()'
function. A user who has the 'FILE' privilege can read any
file on the server host that is either world-readable or
readable by the MySQL server. (This implies the user can read
any file in any database directory, because the server can
access any of those files.)
* Enables creating new files in any directory where the MySQL
server has write access. This includes the server's data
directory containing the files that implement the privilege
tables.
* As of MySQL 5.7.17, enables use of the 'DATA DIRECTORY' or
'INDEX DIRECTORY' table option for the *note 'CREATE TABLE':
create-table. statement.
As a security measure, the server does not overwrite existing files.
To limit the location in which files can be read and written, set the 'secure_file_priv' system variable to a specific directory. See *note server-system-variables::.
'GRANT OPTION'
Enables you to grant to or revoke from other users those privileges that you yourself possess.
'INDEX'
Enables use of statements that create or drop (remove) indexes. 'INDEX' applies to existing tables. If you have the 'CREATE' privilege for a table, you can include index definitions in the *note 'CREATE TABLE': create-table. statement.
'INSERT'
Enables rows to be inserted into tables in a database. 'INSERT' is also required for the note 'ANALYZE TABLE': analyze-table, note 'OPTIMIZE TABLE': optimize-table, and *note 'REPAIR TABLE': repair-table. table-maintenance statements.
'LOCK TABLES'
Enables use of explicit *note 'LOCK TABLES': lock-tables. statements to lock tables for which you have the 'SELECT' privilege. This includes use of write locks, which prevents other sessions from reading the locked table.
'PROCESS'
The 'PROCESS' privilege controls access to information about threads executing within the server (that is, information about statements being executed by sessions). Thread information available using the note 'SHOW PROCESSLIST': show-processlist. statement, the note 'mysqladmin processlist': mysqladmin. command, the note 'INFORMATION_SCHEMA.PROCESSLIST': information-schema-processlist-table. table, and the Performance Schema note 'processlist': performance-schema-processlist-table. table is accessible as follows:
* With the 'PROCESS' privilege, a user has access to information
about all threads, even those belonging to other users.
* Without the 'PROCESS' privilege, nonanonymous users have
access to information about their own threads but not threads
for other users, and anonymous users have no access to thread
information.
Note:
The Performance Schema note 'threads': performance-schema-threads-table. table also provides thread information, but table access uses a different privilege model. See note performance-schema-threads-table::.
The 'PROCESS' privilege also enables use of the note 'SHOW ENGINE': show-engine. statement, access to the 'INFORMATION_SCHEMA' 'InnoDB' tables (tables with names that begin with 'INNODB_'), and (as of MySQL 5.7.31) access to the 'INFORMATION_SCHEMA' note 'FILES': information-schema-files-table. table.
'PROXY'
Enables one user to impersonate or become known as another user. See *note proxy-users::.
'REFERENCES'
Creation of a foreign key constraint requires the 'REFERENCES' privilege for the parent table.
'RELOAD'
The 'RELOAD' enables the following operations:
* Use of the *note 'FLUSH': flush. statement.
* Use of *note 'mysqladmin': mysqladmin. commands that are
equivalent to *note 'FLUSH': flush. operations: 'flush-hosts',
'flush-logs', 'flush-privileges', 'flush-status',
'flush-tables', 'flush-threads', 'refresh', and 'reload'.
The 'reload' command tells the server to reload the grant
tables into memory. 'flush-privileges' is a synonym for
'reload'. The 'refresh' command closes and reopens the log
files and flushes all tables. The other 'flush-XXX' commands
perform functions similar to 'refresh', but are more specific
and may be preferable in some instances. For example, if you
want to flush just the log files, 'flush-logs' is a better
choice than 'refresh'.
* Use of *note 'mysqldump': mysqldump. options that perform
various *note 'FLUSH': flush. operations: '--flush-logs' and
'--master-data'.
* Use of the *note 'RESET': reset. statement.
'REPLICATION CLIENT'
Enables use of the note 'SHOW MASTER STATUS': show-master-status, note 'SHOW SLAVE STATUS': show-slave-status, and *note 'SHOW BINARY LOGS': show-binary-logs. statements.
'REPLICATION SLAVE'
Enables the account to request updates that have been made to databases on the source server, using the note 'SHOW SLAVE HOSTS': show-slave-hosts, note 'SHOW RELAYLOG EVENTS': show-relaylog-events, and note 'SHOW BINLOG EVENTS': show-binlog-events. statements. This privilege is also required to use the note 'mysqlbinlog': mysqlbinlog. options '--read-from-remote-server' ('-R') and '--read-from-remote-master'. Grant this privilege to accounts that are used by replica servers to connect to the current server as their source.
'SELECT'
Enables rows to be selected from tables in a database. note 'SELECT': select. statements require the 'SELECT' privilege only if they actually access tables. Some note 'SELECT': select. statements do not access tables and can be executed without permission for any database. For example, you can use *note 'SELECT': select. as a simple calculator to evaluate expressions that make no reference to tables:
SELECT 1+1;
SELECT PI()*2;
The 'SELECT' privilege is also needed for other statements that read column values. For example, 'SELECT' is needed for columns referenced on the right hand side of COL_NAME=EXPR assignment in note 'UPDATE': update. statements or for columns named in the 'WHERE' clause of note 'DELETE': delete. or *note 'UPDATE': update. statements.
The 'SELECT' privilege is needed for tables or views used with *note 'EXPLAIN': explain, including any underlying tables in view definitions.
'SHOW DATABASES'
Enables the account to see database names by issuing the 'SHOW DATABASE' statement. Accounts that do not have this privilege see only databases for which they have some privileges, and cannot use the statement at all if the server was started with the '--skip-show-database' option.
Caution:
Because a global privilege is considered a privilege for all databases, any global privilege enables a user to see all database names with note 'SHOW DATABASES': show-databases. or by examining the 'INFORMATION_SCHEMA' note 'SCHEMATA': information-schema-schemata-table. table.
'SHOW VIEW'
Enables use of the note 'SHOW CREATE VIEW': show-create-view. statement. This privilege is also needed for views used with note 'EXPLAIN': explain.
'SHUTDOWN'
Enables use of the note 'SHUTDOWN': shutdown. statement, the note 'mysqladmin shutdown': mysqladmin. command, and the 'mysql_shutdown()' (https://dev.mysql.com/doc/c-api/5.7/en/mysql-shutdown.html) C API function.
'SUPER'
Affects the following operations and server behaviors:
* Enables server configuration changes by modifying global
system variables. For some system variables, setting the
session value also requires the 'SUPER' privilege. If a
system variable is restricted and requires a special privilege
to set the session value, the variable description indicates
that restriction. Examples include 'binlog_format',
'sql_log_bin', and 'sql_log_off'. See also *note
system-variable-privileges::.
* Enables changes to global transaction characteristics (see
*note set-transaction::).
* Enables the account to start and stop replication, including
Group Replication.
* Enables use of the *note 'CHANGE MASTER TO': change-master-to.
and *note 'CHANGE REPLICATION FILTER':
change-replication-filter. statements.
* Enables binary log control by means of the *note 'PURGE BINARY
LOGS': purge-binary-logs. and *note 'BINLOG': binlog.
statements.
* Enables setting the effective authorization ID when executing
a view or stored program. A user with this privilege can
specify any account in the 'DEFINER' attribute of a view or
stored program.
* Enables use of the *note 'CREATE SERVER': create-server, *note
'ALTER SERVER': alter-server, and *note 'DROP SERVER':
drop-server. statements.
* Enables use of the *note 'mysqladmin debug': mysqladmin.
command.
* Enables 'InnoDB' encryption key rotation.
* Enables reading the DES key file by the 'DES_ENCRYPT()'
function.
* Enables execution of Version Tokens functions.
* Enables control over client connections not permitted to
non-'SUPER' accounts:
* Enables use of the *note 'KILL': kill. statement or *note
'mysqladmin kill': mysqladmin. command to kill threads
belonging to other accounts. (An account can always kill
its own threads.)
* The server does not execute 'init_connect' system
variable content when 'SUPER' clients connect.
* The server accepts one connection from a 'SUPER' client
even if the connection limit configured by the
'max_connections' system variable is reached.
* A server in offline mode ('offline_mode' enabled) does
not terminate 'SUPER' client connections at the next
client request, and accepts new connections from 'SUPER'
clients.
* Updates can be performed even when the 'read_only' system
variable is enabled. This applies to explicit table
updates, and to use of account-management statements such
as *note 'GRANT': grant. and *note 'REVOKE': revoke. that
update tables implicitly.
You may also need the 'SUPER' privilege to create or alter stored functions if binary logging is enabled, as described in *note stored-programs-logging::.
'TRIGGER'
Enables trigger operations. You must have this privilege for a table to create, drop, execute, or display triggers for that table.
When a trigger is activated (by a user who has privileges to execute note 'INSERT': insert, note 'UPDATE': update, or *note 'DELETE': delete. statements for the table associated with the trigger), trigger execution requires that the user who defined the trigger still have the 'TRIGGER' privilege for the table.
'UPDATE'
Enables rows to be updated in tables in a database.
'USAGE'
This privilege specifier stands for 'no privileges.' It is used at the global level with note 'GRANT': grant. to modify account attributes such as resource limits or SSL characteristics without naming specific account privileges in the privilege list. note 'SHOW GRANTS': show-grants. displays 'USAGE' to indicate that an account has no privileges at a privilege level.
Privilege-Granting Guidelines
It is a good idea to grant to an account only those privileges that it needs. You should exercise particular caution in granting the 'FILE' and administrative privileges:
'FILE' can be abused to read into a database table any files that the MySQL server can read on the server host. This includes all world-readable files and files in the server's data directory. The table can then be accessed using *note 'SELECT': select. to transfer its contents to the client host.
'GRANT OPTION' enables users to give their privileges to other users. Two users that have different privileges and with the 'GRANT OPTION' privilege are able to combine privileges.
'ALTER' may be used to subvert the privilege system by renaming tables.
'SHUTDOWN' can be abused to deny service to other users entirely by terminating the server.
'PROCESS' can be used to view the plain text of currently executing statements, including statements that set or change passwords.
'SUPER' can be used to terminate other sessions or change how the server operates.
Privileges granted for the 'mysql' system database itself can be used to change passwords and other access privilege information:
* Passwords are stored encrypted, so a malicious user cannot
simply read them to know the plain text password. However, a
user with write access to the 'mysql.user' system table
'authentication_string' column can change an account's
password, and then connect to the MySQL server using that
account.
* 'INSERT' or 'UPDATE' granted for the 'mysql' system database
enable a user to add privileges or modify existing privileges,
respectively.
* 'DROP' for the 'mysql' system database enables a user to
remote privilege tables, or even the database itself.
File: manual.info.tmp, Node: grant-tables, Next: account-names, Prev: privileges-provided, Up: access-control
The 'mysql' system database includes several grant tables that contain information about user accounts and the privileges held by them. This section describes those tables. For information about other tables in the system database, see *note system-schema::.
The discussion here describes the underlying structure of the grant tables and how the server uses their contents when interacting with clients. However, normally you do not modify the grant tables directly. Modifications occur indirectly when you use account-management statements such as note 'CREATE USER': create-user, note 'GRANT': grant, and note 'REVOKE': revoke. to set up accounts and control the privileges available to each one. See note account-management-statements::. When you use such statements to perform account manipulations, the server modifies the grant tables on your behalf.
Note:
Direct modification of grant tables using statements such as note 'INSERT': insert, note 'UPDATE': update, or *note 'DELETE': delete. is discouraged and done at your own risk. The server is free to ignore rows that become malformed as a result of such modifications.
As of MySQL 5.7.18, for any operation that modifies a grant table, the server checks whether the table has the expected structure and produces an error if not. To update the tables to the expected structure, perform the MySQL upgrade procedure. See *note upgrading::.
*note grant-tables-overview::
*note grant-tables-user-db::
*note grant-tables-tables-priv-columns-priv::
*note grant-tables-procs-priv::
*note grant-tables-proxies-priv::
*note grant-tables-scope-column-properties::
*note grant-tables-privilege-column-properties::
Grant Table Overview
These 'mysql' database tables contain grant information:
'user': User accounts, global privileges, and other nonprivilege columns.
'db': Database-level privileges.
'tables_priv': Table-level privileges.
'columns_priv': Column-level privileges.
'procs_priv': Stored procedure and function privileges.
'proxies_priv': Proxy-user privileges.
Each grant table contains scope columns and privilege columns:
Scope columns determine the scope of each row in the tables; that is, the context in which the row applies. For example, a 'user' table row with 'Host' and 'User' values of ''h1.example.net'' and ''bob'' applies to authenticating connections made to the server from the host 'h1.example.net' by a client that specifies a user name of 'bob'. Similarly, a 'db' table row with 'Host', 'User', and 'Db' column values of ''h1.example.net'', ''bob'' and ''reports'' applies when 'bob' connects from the host 'h1.example.net' to access the 'reports' database. The 'tables_priv' and 'columns_priv' tables contain scope columns indicating tables or table/column combinations to which each row applies. The 'procs_priv' scope columns indicate the stored routine to which each row applies.
Privilege columns indicate which privileges a table row grants; that is, which operations it permits to be performed. The server combines the information in the various grant tables to form a complete description of a user's privileges. *note request-access::, describes the rules for this.
In addition, a grant table may contain columns used for purposes other than scope or privilege assessment.
The server uses the grant tables in the following manner:
The 'user' table scope columns determine whether to reject or permit incoming connections. For permitted connections, any privileges granted in the 'user' table indicate the user's global privileges. Any privileges granted in this table apply to all databases on the server.
Caution:
Because a global privilege is considered a privilege for all databases, any global privilege enables a user to see all database names with note 'SHOW DATABASES': show-databases. or by examining the 'INFORMATION_SCHEMA' note 'SCHEMATA': information-schema-schemata-table. table.
The 'db' table scope columns determine which users can access which databases from which hosts. The privilege columns determine the permitted operations. A privilege granted at the database level applies to the database and to all objects in the database, such as tables and stored programs.
The 'tables_priv' and 'columns_priv' tables are similar to the 'db' table, but are more fine-grained: They apply at the table and column levels rather than at the database level. A privilege granted at the table level applies to the table and to all its columns. A privilege granted at the column level applies only to a specific column.
The 'procs_priv' table applies to stored routines (stored procedures and functions). A privilege granted at the routine level applies only to a single procedure or function.
The 'proxies_priv' table indicates which users can act as proxies for other users and whether a user can grant the 'PROXY' privilege to other users.
The server reads the contents of the grant tables into memory when it starts. You can tell it to reload the tables by issuing a 'FLUSH PRIVILEGES' statement or executing a note 'mysqladmin flush-privileges': mysqladmin. or note 'mysqladmin reload': mysqladmin. command. Changes to the grant tables take effect as indicated in *note privilege-changes::.
When you modify an account, it is a good idea to verify that your changes have the intended effect. To check the privileges for a given account, use the *note 'SHOW GRANTS': show-grants. statement. For example, to determine the privileges that are granted to an account with user name and host name values of 'bob' and 'pc84.example.com', use this statement:
SHOW GRANTS FOR 'bob'@'pc84.example.com';
To display nonprivilege properties of an account, use *note 'SHOW CREATE USER': show-create-user.:
SHOW CREATE USER 'bob'@'pc84.example.com';
The user and db Grant Tables
The server uses the 'user' and 'db' tables in the 'mysql' database at both the first and second stages of access control (see *note access-control::). The columns in the 'user' and 'db' tables are shown here.
user and db Table Columns
Table Name 'user' 'db'
Scope columns
'Host' 'Host'
'User' 'Db'
'User'
Privilege columns
'Select_priv' 'Select_priv'
'Insert_priv' 'Insert_priv'
'Update_priv' 'Update_priv'
'Delete_priv' 'Delete_priv'
'Index_priv' 'Index_priv'
'Alter_priv' 'Alter_priv'
'Create_priv' 'Create_priv'
'Drop_priv' 'Drop_priv'
'Grant_priv' 'Grant_priv'
'Create_view_priv' 'Create_view_priv'
'Show_view_priv' 'Show_view_priv'
'Create_routine_priv' 'Create_routine_priv'
'Alter_routine_priv' 'Alter_routine_priv'
'Execute_priv' 'Execute_priv'
'Trigger_priv' 'Trigger_priv'
'Event_priv' 'Event_priv'
'Create_tmp_table_priv' 'Create_tmp_table_priv'
'Lock_tables_priv' 'Lock_tables_priv'
'References_priv' 'References_priv'
'Reload_priv'
'Shutdown_priv'
'Process_priv'
'File_priv'
'Show_db_priv'
'Super_priv'
'Repl_slave_priv'
'Repl_client_priv'
'Create_user_priv'
'Create_tablespace_priv'
Security columns
'ssl_type'
'ssl_cipher'
'x509_issuer'
'x509_subject'
'plugin'
'authentication_string'
'password_expired'
'password_last_changed'
'password_lifetime'
'account_locked'
Resource control columns
'max_questions'
'max_updates'
'max_connections'
'max_user_connections'
The 'user' table 'plugin' and 'authentication_string' columns store authentication plugin and credential information.
The server uses the plugin named in the 'plugin' column of an account row to authenticate connection attempts for the account.
The 'plugin' column must be nonempty. At startup, and at runtime when 'FLUSH PRIVILEGES' is executed, the server checks 'user' table rows. For any row with an empty 'plugin' column, the server writes a warning to the error log of this form:
[Warning] User entry 'USER_NAME'@'HOST_NAME' has an empty plugin
value. The user will be ignored and no one can login with this user
anymore.
To address this problem, see *note account-upgrades::.
The 'password_expired' column permits DBAs to expire account passwords and require users to reset their password. The default 'password_expired' value is ''N'', but can be set to ''Y'' with the note 'ALTER USER': alter-user. statement. After an account's password has been expired, all operations performed by the account in subsequent connections to the server result in an error until the user issues an note 'ALTER USER': alter-user. statement to establish 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.
'password_last_changed' is a 'TIMESTAMP' column indicating when the password was last changed. The value is non-'NULL' only for accounts that use MySQL built-in authentication methods (accounts that use an authentication plugin of 'mysql_native_password' or 'sha256_password'). The value is 'NULL' for other accounts, such as those authenticated using an external authentication system.
'password_last_changed' is updated by the note 'CREATE USER': create-user, note 'ALTER USER': alter-user, and note 'SET PASSWORD': set-password. statements, and by note 'GRANT': grant. statements that create an account or change an account password.
'password_lifetime' indicates the account password lifetime, in days. If the password is past its lifetime (assessed using the 'password_last_changed' column), the server considers the password expired when clients connect using the account. A value of N greater than zero means that the password must be changed every N days. A value of 0 disables automatic password expiration. If the value is 'NULL' (the default), the global expiration policy applies, as defined by the 'default_password_lifetime' system variable.
'account_locked' indicates whether the account is locked (see *note account-locking::).
The tables_priv and columns_priv Grant Tables
During the second stage of access control, the server performs request verification to ensure that each client has sufficient privileges for each request that it issues. In addition to the 'user' and 'db' grant tables, the server may also consult the 'tables_priv' and 'columns_priv' tables for requests that involve tables. The latter tables provide finer privilege control at the table and column levels. They have the columns shown in the following table.
tables_priv and columns_priv Table Columns
Table Name 'tables_priv' 'columns_priv'
Scope columns
'Host' 'Host'
'Db' 'Db'
'User' 'User'
'Table_name' 'Table_name'
'Column_name'
Privilege columns
'Table_priv' 'Column_priv'
'Column_priv'
Other columns
'Timestamp' 'Timestamp'
'Grantor'
The 'Timestamp' and 'Grantor' columns are set to the current timestamp and the 'CURRENT_USER' value, respectively, but are otherwise unused.
The procs_priv Grant Table
For verification of requests that involve stored routines, the server may consult the 'procs_priv' table, which has the columns shown in the following table.
procs_priv Table Columns
Table Name 'procs_priv'
Scope 'Host' columns
'Db'
'User'
'Routine_name'
'Routine_type'
Privilege 'Proc_priv' columns
Other 'Timestamp' columns
'Grantor'
The 'Routine_type' column is an *note 'ENUM': enum. column with values of ''FUNCTION'' or ''PROCEDURE'' to indicate the type of routine the row refers to. This column enables privileges to be granted separately for a function and a procedure with the same name.
The 'Timestamp' and 'Grantor' columns are unused.
The proxies_priv Grant Table
The 'proxies_priv' table records information about proxy accounts. It has these columns:
'Host', 'User': The proxy account; that is, the account that has the 'PROXY' privilege for the proxied account.
'Proxied_host', 'Proxied_user': The proxied account.
'Grantor', 'Timestamp': Unused.
'With_grant': Whether the proxy account can grant the 'PROXY' privilege to other accounts.
For an account to be able to grant the 'PROXY' privilege to other accounts, it must have a row in the 'proxies_priv' table with 'With_grant' set to 1 and 'Proxied_host' and 'Proxied_user' set to indicate the account or accounts for which the privilege can be granted. For example, the ''root'@'localhost'' account created during MySQL installation has a row in the 'proxies_priv' table that enables granting the 'PROXY' privilege for '''@''', that is, for all users and all hosts. This enables 'root' to set up proxy users, as well as to delegate to other accounts the authority to set up proxy users. See *note proxy-users::.
Grant Table Scope Column Properties
Scope columns in the grant tables contain strings. The default value for each is the empty string. The following table shows the number of characters permitted in each column.
Grant Table Scope Column Lengths
Column Name Maximum Permitted Characters
'Host', 'Proxied_host' 60
'User', 'Proxied_user' 32
'Password' 41
'Db' 64
'Table_name' 64
'Column_name' 64
'Routine_name' 64
'Host' and 'Proxied_host' values are converted to lowercase before being stored in the grant tables.
For access-checking purposes, comparisons of 'User', 'Proxied_user', 'Password', 'authentication_string', 'Db', and 'Table_name' values are case-sensitive. Comparisons of 'Host', 'Proxied_host', 'Column_name', and 'Routine_name' values are not case-sensitive.
Grant Table Privilege Column Properties
The 'user' and 'db' tables list each privilege in a separate column that is declared as 'ENUM('N','Y') DEFAULT 'N''. In other words, each privilege can be disabled or enabled, with the default being disabled.
The 'tables_priv', 'columns_priv', and 'procs_priv' tables declare the privilege columns as *note 'SET': set. columns. Values in these columns can contain any combination of the privileges controlled by the table. Only those privileges listed in the column value are enabled.
Set-Type Privilege Column Values
Table Name Column Name Possible Set Elements
'tables_priv'
'Table_priv' ''Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter', 'Create View', 'Show view', 'Trigger''
'tables_priv'
'Column_priv' ''Select', 'Insert', 'Update', 'References''
'columns_priv'
'Column_priv' ''Select', 'Insert', 'Update', 'References''
'procs_priv'
'Proc_priv' ''Execute', 'Alter Routine', 'Grant''
Only the 'user' table specifies administrative privileges, such as 'RELOAD' and 'SHUTDOWN'. Administrative operations are operations on the server itself and are not database-specific, so there is no reason to list these privileges in the other grant tables. Consequently, the server need consult only the 'user' table to determine whether a user can perform an administrative operation.
The 'FILE' privilege also is specified only in the 'user' table. It is not an administrative privilege as such, but a user's ability to read or write files on the server host is independent of the database being accessed.
File: manual.info.tmp, Node: account-names, Next: connection-access, Prev: grant-tables, Up: access-control
MySQL account names consist of a user name and a host name, which enables creation of distinct accounts for users with the same user name who connect from different hosts. This section describes the syntax for account names, including special values and wildcard rules.
Account names appear in SQL statements such as note 'CREATE USER': create-user, note 'GRANT': grant, and *note 'SET PASSWORD': set-password. and follow these rules:
Account name syntax is ''USER_NAME'@'HOST_NAME''.
The '@'HOST_NAME'' part is optional. An account name consisting only of a user name is equivalent to ''USER_NAME'@'%''. For example, ''me'' is equivalent to ''me'@'%''.
The user name and host name need not be quoted if they are legal as unquoted identifiers. Quotes must be used if a USER_NAME string contains special characters (such as space or '-'), or a HOST_NAME string contains special characters or wildcard characters (such as '.' or '%'). For example, in the account name ''test-user'@'%.com'', both the user name and host name parts require quotes.
Quote user names and host names as identifiers or as strings, using either backticks ('`'), single quotation marks ('''), or double quotation marks ('"'). For string-quoting and identifier-quoting guidelines, see note string-literals::, and note identifiers::.
The user name and host name parts, if quoted, must be quoted separately. That is, write ''me'@'localhost'', not ''me@localhost''. The latter is actually equivalent to ''me@localhost'@'%''.
A reference to the 'CURRENT_USER' or 'CURRENT_USER()' function is equivalent to specifying the current client's user name and host name literally.
MySQL stores account names in grant tables in the 'mysql' system database using separate columns for the user name and host name parts:
The 'user' table contains one row for each account. The 'User' and 'Host' columns store the user name and host name. This table also indicates which global privileges the account has.
Other grant tables indicate privileges an account has for databases and objects within databases. These tables have 'User' and 'Host' columns to store the account name. Each row in these tables associates with the account in the 'user' table that has the same 'User' and 'Host' values.
For access-checking purposes, comparisons of User values are case-sensitive. Comparisons of Host values are not case-sensitive.
For additional detail about the properties of user names and host names as stored in the grant tables, such as maximum length, see *note grant-tables-scope-column-properties::.
User names and host names have certain special values or wildcard conventions, as described following.
The user name part of an account name is either a nonblank value that literally matches the user name for incoming connection attempts, or a blank value (the empty string) that matches any user name. An account with a blank user name is an anonymous user. To specify an anonymous user in SQL statements, use a quoted empty user name part, such as '''@'localhost''.
The host name part of an account name can take many forms, and wildcards are permitted:
A host value can be a host name or an IP address (IPv4 or IPv6). The name ''localhost'' indicates the local host. The IP address ''127.0.0.1'' indicates the IPv4 loopback interface. The IP address ''::1'' indicates the IPv6 loopback interface.
The '%' and '_' wildcard characters are permitted in host name or IP address values. These have the same meaning as for pattern-matching operations performed with the 'LIKE' operator. For example, a host value of ''%'' matches any host name, whereas a value of ''%.mysql.com'' matches any host in the 'mysql.com' domain. ''198.51.100.%'' matches any host in the 198.51.100 class C network.
Because IP wildcard values are permitted in host values (for example, ''198.51.100.%'' to match every host on a subnet), someone could try to exploit this capability by naming a host '198.51.100.somewhere.com'. To foil such attempts, MySQL does not perform matching on host names that start with digits and a dot. For example, if a host is named '1.2.example.com', its name never matches the host part of account names. An IP wildcard value can match only IP addresses, not host names.
For a host value specified as an IPv4 address, a netmask can be given to indicate how many address bits to use for the network number. Netmask notation cannot be used for IPv6 addresses.
The syntax is 'HOST_IP/NETMASK'. For example:
CREATE USER 'david'@'198.51.100.0/255.255.255.0';
This enables 'david' to connect from any client host having an IP address CLIENT_IP for which the following condition is true:
CLIENT_IP & NETMASK = HOST_IP
That is, for the *note 'CREATE USER': create-user. statement just shown:
CLIENT_IP & 255.255.255.0 = 198.51.100.0
IP addresses that satisfy this condition range from '198.51.100.0' to '198.51.100.255'.
A netmask typically begins with bits set to 1, followed by bits set to 0. Examples:
* '198.0.0.0/255.0.0.0': Any host on the 198 class A network
* '198.51.0.0/255.255.0.0': Any host on the 198.51 class B
network
* '198.51.100.0/255.255.255.0': Any host on the 198.51.100 class
C network
* '198.51.100.1': Only the host with this specific IP address
The server performs matching of host values in account names against the client host using the value returned by the system DNS resolver for the client host name or IP address. Except in the case that the account host value is specified using netmask notation, the server performs this comparison as a string match, even for an account host value given as an IP address. This means that you should specify account host values in the same format used by DNS. Here are examples of problems to watch out for:
Suppose that a host on the local network has a fully qualified name of 'host1.example.com'. If DNS returns name lookups for this host as 'host1.example.com', use that name in account host values. If DNS returns just 'host1', use 'host1' instead.
If DNS returns the IP address for a given host as '198.51.100.2', that matches an account host value of '198.51.100.2' but not '198.051.100.2'. Similarly, it matches an account host pattern like '198.51.100.%' but not '198.051.100.%'.
To avoid problems like these, it is advisable to check the format in which your DNS returns host names and addresses. Use values in the same format in MySQL account names.
File: manual.info.tmp, Node: connection-access, Next: request-access, Prev: account-names, Up: access-control
When you attempt to connect to a MySQL server, the server accepts or rejects the connection based on these conditions:
Your identity and whether you can verify it by supplying the proper credentials.
Whether your account is locked or unlocked.
The server checks credentials first, then account locking state. A failure at either step causes the server to deny access to you completely. Otherwise, the server accepts the connection, and then enters Stage 2 and waits for requests.
The server performs identity and credentials checking using columns in the 'user' table, accepting the connection only if these conditions are satisfied:
The client host name and user name match the 'Host' and 'User' columns in some 'user' table row. For the rules governing permissible 'Host' and 'User' values, see *note account-names::.
The client supplies the credentials specified in the row (for example, a password), as indicated by the 'authentication_string' column. Credentials are interpreted using the authentication plugin named in the 'plugin' column.
The row indicates that the account is unlocked. Locking state is recorded in the 'account_locked' column, which must have a value of ''N''. Account locking can be set or changed with the note 'CREATE USER': create-user. or note 'ALTER USER': alter-user. statement.
Your identity is based on two pieces of information:
Your MySQL user name.
The client host from which you connect.
If the 'User' column value is nonblank, the user name in an incoming connection must match exactly. If the 'User' value is blank, it matches any user name. If the 'user' table row that matches an incoming connection has a blank user name, the user is considered to be an anonymous user with no name, not a user with the name that the client actually specified. This means that a blank user name is used for all further access checking for the duration of the connection (that is, during Stage 2).
The 'authentication_string' column can be blank. This is not a wildcard and does not mean that any password matches. It means that the user must connect without specifying a password. The authentication method implemented by the plugin that authenticates the client may or may not use the password in the 'authentication_string' column. In this case, it is possible that an external password is also used to authenticate to the MySQL server.
Nonblank password values stored in the 'authentication_string' column of the 'user' table are encrypted. MySQL does not store passwords as cleartext for anyone to see. Rather, the password supplied by a user who is attempting to connect is encrypted (using the password hashing method implemented by the account authentication plugin). The encrypted password then is used during the connection process when checking whether the password is correct. This is done without the encrypted password ever traveling over the connection. See *note user-names::.
From the MySQL server's point of view, the encrypted password is the real password, so you should never give anyone access to it. In particular, do not give nonadministrative users read access to tables in the 'mysql' system database.
The following table shows how various combinations of 'User' and 'Host' values in the 'user' table apply to incoming connections.
'User' 'Host' Value Permissible Connections Value
''fred''
''h1.example.net'''fred', connecting from 'h1.example.net'
''''
''h1.example.net''Any user, connecting from 'h1.example.net'
''fred''
''%'' 'fred', connecting from any host
''''
''%'' Any user, connecting from any host
''fred''
''%.example.net'''fred', connecting from any host in the 'example.net' domain
''fred''
''x.example.%'''fred', connecting from 'x.example.net', 'x.example.com', 'x.example.edu', and so on; this is probably not useful
''fred''
''198.51.100.177'''fred', connecting from the host with IP address '198.51.100.177'
''fred''
''198.51.100.%'''fred', connecting from any host in the '198.51.100' class C subnet
''fred''
''198.51.100.0/255.255.255.0''Same as previous example
It is possible for the client host name and user name of an incoming connection to match more than one row in the 'user' table. The preceding set of examples demonstrates this: Several of the entries shown match a connection from 'h1.example.net' by 'fred'.
When multiple matches are possible, the server must determine which of them to use. It resolves this issue as follows:
Whenever the server reads the 'user' table into memory, it sorts the rows.
When a client attempts to connect, the server looks through the rows in sorted order.
The server uses the first row that matches the client host name and user name.
The server uses sorting rules that order rows with the most-specific 'Host' values first:
Literal IP addresses and host names are the most specific.
The specificity of a literal IP address is not affected by whether it has a netmask, so '198.51.100.13' and '198.51.100.0/255.255.255.0' are considered equally specific.
The pattern ''%'' means 'any host' and is least specific.
The empty string '''' also means 'any host' but sorts after ''%''.
Non-TCP (socket file, named pipe, and shared memory) connections are treated as local connections and match a host part of 'localhost' if there are any such accounts, or host parts with wildcards that match 'localhost' otherwise (for example, 'local%', 'l%', '%').
Rows with the same 'Host' value are ordered with the most-specific 'User' values first. A blank 'User' value means 'any user' and is least specific, so for rows with the same 'Host' value, nonanonymous users sort before anonymous users.
For rows with equally-specific 'Host' and 'User' values, the order is nondeterministic.
To see how this works, suppose that the 'user' table looks like this:
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
+-----------+----------+-
When the server reads the table into memory, it sorts the rows using the rules just described. The result after sorting looks like this:
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-
When a client attempts to connect, the server looks through the sorted rows and uses the first match found. For a connection from 'localhost' by 'jeffrey', two of the rows from the table match: the one with 'Host' and 'User' values of ''localhost'' and '''', and the one with values of ''%'' and ''jeffrey''. The ''localhost'' row appears first in sorted order, so that is the one the server uses.
Here is another example. Suppose that the 'user' table looks like this:
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| % | jeffrey | ...
| h1.example.net | | ...
+----------------+----------+-
The sorted table looks like this:
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| h1.example.net | | ...
| % | jeffrey | ...
+----------------+----------+-
The first row matches a connection by any user from 'h1.example.net', whereas the second row matches a connection by 'jeffrey' from any host.
Note:
It is a common misconception to think that, for a given user name, all rows that explicitly name that user are used first when the server attempts to find a match for the connection. This is not true. The preceding example illustrates this, where a connection from 'h1.example.net' by 'jeffrey' is first matched not by the row containing ''jeffrey'' as the 'User' column value, but by the row with no user name. As a result, 'jeffrey' is authenticated as an anonymous user, even though he specified a user name when connecting.
If you are able to connect to the server, but your privileges are not what you expect, you probably are being authenticated as some other account. To find out what account the server used to authenticate you, use the 'CURRENT_USER()' function. (See *note information-functions::.) It returns a value in 'USER_NAME@HOST_NAME' format that indicates the 'User' and 'Host' values from the matching 'user' table row. Suppose that 'jeffrey' connects and issues the following query:
mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+
The result shown here indicates that the matching 'user' table row had a blank 'User' column value. In other words, the server is treating 'jeffrey' as an anonymous user.
Another way to diagnose authentication problems is to print out the 'user' table and sort it by hand to see where the first match is being made.
File: manual.info.tmp, Node: request-access, Next: creating-accounts, Prev: connection-access, Up: access-control
After the server accepts a connection, it enters Stage 2 of access control. For each request that you issue through the connection, the server determines what operation you want to perform, then checks whether your privileges are sufficient. This is where the privilege columns in the grant tables come into play. These privileges can come from any of the 'user', 'db', 'tables_priv', 'columns_priv', or 'procs_priv' tables. (You may find it helpful to refer to *note grant-tables::, which lists the columns present in each grant table.)
The 'user' table grants global privileges. The 'user' table row for an account indicates the account privileges that apply on a global basis no matter what the default database is. For example, if the 'user' table grants you the 'DELETE' privilege, you can delete rows from any table in any database on the server host. It is wise to grant privileges in the 'user' table only to people who need them, such as database administrators. For other users, leave all privileges in the 'user' table set to ''N'' and grant privileges at more specific levels only (for particular databases, tables, columns, or routines).
The 'db' table grants database-specific privileges. Values in the scope columns of this table can take the following forms:
A blank 'User' value matches the anonymous user. A nonblank value matches literally; there are no wildcards in user names.
The wildcard characters '%' and '' can be used in the 'Host' and 'Db' columns. These have the same meaning as for pattern-matching operations performed with the 'LIKE' operator. If you want to use either character literally when granting privileges, you must escape it with a backslash. For example, to include the underscore character ('') as part of a database name, specify it as '_' in the *note 'GRANT': grant. statement.
A ''%'' or blank 'Host' value means 'any host.'
A ''%'' or blank 'Db' value means 'any database.'
The server reads the 'db' table into memory and sorts it at the same time that it reads the 'user' table. The server sorts the 'db' table based on the 'Host', 'Db', and 'User' scope columns. As with the 'user' table, sorting puts the most-specific values first and least-specific values last, and when the server looks for matching rows, it uses the first match that it finds.
The 'tables_priv', 'columns_priv', and 'procs_priv' tables grant table-specific, column-specific, and routine-specific privileges. Values in the scope columns of these tables can take the following forms:
The wildcard characters '%' and '_' can be used in the 'Host' column. These have the same meaning as for pattern-matching operations performed with the 'LIKE' operator.
A ''%'' or blank 'Host' value means 'any host.'
The 'Db', 'Table_name', 'Column_name', and 'Routine_name' columns cannot contain wildcards or be blank.
The server sorts the 'tables_priv', 'columns_priv', and 'procs_priv' tables based on the 'Host', 'Db', and 'User' columns. This is similar to 'db' table sorting, but simpler because only the 'Host' column can contain wildcards.
The server uses the sorted tables to verify each request that it receives. For requests that require administrative privileges such as 'SHUTDOWN' or 'RELOAD', the server checks only the 'user' table row because that is the only table that specifies administrative privileges. The server grants access if the row permits the requested operation and denies access otherwise. For example, if you want to execute *note 'mysqladmin shutdown': mysqladmin. but your 'user' table row does not grant the 'SHUTDOWN' privilege to you, the server denies access without even checking the 'db' table. (The latter table contains no 'Shutdown_priv' column, so there is no need to check it.)
For database-related requests (note 'INSERT': insert, note 'UPDATE': update, and so on), the server first checks the user's global privileges in the 'user' table row. If the row permits the requested operation, access is granted. If the global privileges in the 'user' table are insufficient, the server determines the user's database-specific privileges from the 'db' table:
The server looks in the 'db' table for a match on the 'Host', 'Db', and 'User' columns.
The 'Host' and 'User' columns are matched to the connecting user's host name and MySQL user name.
The 'Db' column is matched to the database that the user wants to access.
If there is no row for the 'Host' and 'User', access is denied.
After determining the database-specific privileges granted by the 'db' table rows, the server adds them to the global privileges granted by the 'user' table. If the result permits the requested operation, access is granted. Otherwise, the server successively checks the user's table and column privileges in the 'tables_priv' and 'columns_priv' tables, adds those to the user's privileges, and permits or denies access based on the result. For stored-routine operations, the server uses the 'procs_priv' table rather than 'tables_priv' and 'columns_priv'.
Expressed in boolean terms, the preceding description of how a user's privileges are calculated may be summarized like this:
global privileges
OR database privileges
OR table privileges
OR column privileges
OR routine privileges
It may not be apparent why, if the global privileges are initially found to be insufficient for the requested operation, the server adds those privileges to the database, table, and column privileges later. The reason is that a request might require more than one type of privilege. For example, if you execute an *note 'INSERT INTO ... SELECT': insert-select. statement, you need both the 'INSERT' and the 'SELECT' privileges. Your privileges might be such that the 'user' table row grants one privilege global and the 'db' table row grants the other specifically for the relevant database. In this case, you have the necessary privileges to perform the request, but the server cannot tell that from either your global or database privileges alone. It must make an access-control decision based on the combined privileges.
File: manual.info.tmp, Node: creating-accounts, Next: reserved-accounts, Prev: request-access, Up: access-control
To manage MySQL accounts, use the SQL statements intended for that purpose:
note 'CREATE USER': create-user. and note 'DROP USER': drop-user. create and remove accounts.
note 'GRANT': grant. and note 'REVOKE': revoke. assign privileges to and revoke privileges from accounts.
*note 'SHOW GRANTS': show-grants. displays account privilege assignments.
Account-management statements cause the server to make appropriate modifications to the underlying grant tables, which are discussed in *note grant-tables::.
Note:
Direct modification of grant tables using statements such as note 'INSERT': insert, note 'UPDATE': update, or *note 'DELETE': delete. is discouraged and done at your own risk. The server is free to ignore rows that become malformed as a result of such modifications.
As of MySQL 5.7.18, for any operation that modifies a grant table, the server checks whether the table has the expected structure and produces an error if not. *note 'mysql_upgrade': mysql-upgrade. must be run to update the tables to the expected structure.
Another option for creating accounts is to use the GUI tool MySQL Workbench. Also, several third-party programs offer capabilities for MySQL account administration. 'phpMyAdmin' is one such program.
This section discusses the following topics:
*note creating-accounts-granting-privileges::
*note checking-account-privileges::
*note revoking-account-privileges::
*note dropping-accounts::
For additional information about the statements discussed here, see *note account-management-statements::.
Creating Accounts and Granting Privileges
The following examples show how to use the *note 'mysql': mysql. client program to set up new accounts. These examples assume that the MySQL 'root' account has the 'CREATE USER' privilege and all privileges that it grants to other accounts.
At the command line, connect to the server as the MySQL 'root' user, supplying the appropriate password at the password prompt:
$> mysql -u root -p
Enter password: (ENTER ROOT PASSWORD HERE)
After connecting to the server, you can add new accounts. The following example uses note 'CREATE USER ': create-user. and note 'GRANT': grant. statements to set up four accounts (where you see ''PASSWORD'', substitute an appropriate password):
CREATE USER 'finley'@'localhost'
IDENTIFIED BY 'PASSWORD';
GRANT ALL
ON *.*
TO 'finley'@'localhost'
WITH GRANT OPTION;
CREATE USER 'finley'@'%.example.com'
IDENTIFIED BY 'PASSWORD';
GRANT ALL
ON *.*
TO 'finley'@'%.example.com'
WITH GRANT OPTION;
CREATE USER 'admin'@'localhost'
IDENTIFIED BY 'PASSWORD';
GRANT RELOAD,PROCESS
ON *.*
TO 'admin'@'localhost';
CREATE USER 'dummy'@'localhost';
The accounts created by those statements have the following properties:
Two accounts have a user name of 'finley'. Both are superuser accounts with full global privileges to do anything. The ''finley'@'localhost'' account can be used only when connecting from the local host. The ''finley'@'%.example.com'' account uses the ''%'' wildcard in the host part, so it can be used to connect from any host in the 'example.com' domain.
The ''finley'@'localhost'' account is necessary if there is an anonymous-user account for 'localhost'. Without the ''finley'@'localhost'' account, that anonymous-user account takes precedence when 'finley' connects from the local host and 'finley' is treated as an anonymous user. The reason for this is that the anonymous-user account has a more specific 'Host' column value than the ''finley'@'%'' account and thus comes earlier in the 'user' table sort order. (For information about 'user' table sorting, see *note connection-access::.)
The ''admin'@'localhost'' account can be used only by 'admin' to connect from the local host. It is granted the global 'RELOAD' and 'PROCESS' administrative privileges. These privileges enable the 'admin' user to execute the note 'mysqladmin reload': mysqladmin, note 'mysqladmin refresh': mysqladmin, and note 'mysqladmin flush-XXX': mysqladmin. commands, as well as note 'mysqladmin processlist': mysqladmin. . No privileges are granted for accessing any databases. You could add such privileges using *note 'GRANT': grant. statements.
The ''dummy'@'localhost'' account has no password (which is insecure and not recommended). This account can be used only to connect from the local host. No privileges are granted. It is assumed that you grant specific privileges to the account using *note 'GRANT': grant. statements.
The previous example grants privileges at the global level. The next example creates three accounts and grants them access at lower levels; that is, to specific databases or objects within databases. Each account has a user name of 'custom', but the host name parts differ:
CREATE USER 'custom'@'localhost'
IDENTIFIED BY 'PASSWORD';
GRANT ALL
ON bankaccount.*
TO 'custom'@'localhost';
CREATE USER 'custom'@'host47.example.com'
IDENTIFIED BY 'PASSWORD';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON expenses.*
TO 'custom'@'host47.example.com';
CREATE USER 'custom'@'%.example.com'
IDENTIFIED BY 'PASSWORD';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON customer.addresses
TO 'custom'@'%.example.com';
The three accounts can be used as follows:
The ''custom'@'localhost'' account has all database-level privileges to access the 'bankaccount' database. The account can be used to connect to the server only from the local host.
The ''custom'@'host47.example.com'' account has specific database-level privileges to access the 'expenses' database. The account can be used to connect to the server only from the host 'host47.example.com'.
The ''custom'@'%.example.com'' account has specific table-level privileges to access the 'addresses' table in the 'customer' database, from any host in the 'example.com' domain. The account can be used to connect to the server from all machines in the domain due to use of the '%' wildcard character in the host part of the account name.
Checking Account Privileges and Properties
To see the privileges for an account, use *note 'SHOW GRANTS': show-grants.:
mysql> SHOW GRANTS FOR 'admin'@'localhost';
+-----------------------------------------------------+
| Grants for admin@localhost |
+-----------------------------------------------------+
| GRANT RELOAD, PROCESS ON *.* TO 'admin'@'localhost' |
+-----------------------------------------------------+
To see nonprivilege properties for an account, use *note 'SHOW CREATE USER': show-create-user.:
mysql> SHOW CREATE USER 'admin'@'localhost'\G
*************************** 1. row ***************************
CREATE USER for admin@localhost: CREATE USER 'admin'@'localhost'
IDENTIFIED WITH 'mysql_native_password'
AS '*67ACDEBDAB923990001F0FFB017EB8ED41861105'
REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK
Revoking Account Privileges
To revoke account privileges, use the *note 'REVOKE': revoke. statement. Privileges can be revoked at different levels, just as they can be granted at different levels.
Revoke global privileges:
REVOKE ALL
ON *.*
FROM 'finley'@'%.example.com';
REVOKE RELOAD
ON *.*
FROM 'admin'@'localhost';
Revoke database-level privileges:
REVOKE CREATE,DROP
ON expenses.*
FROM 'custom'@'host47.example.com';
Revoke table-level privileges:
REVOKE INSERT,UPDATE,DELETE
ON customer.addresses
FROM 'custom'@'%.example.com';
To check the effect of privilege revocation, use *note 'SHOW GRANTS': show-grants.:
mysql> SHOW GRANTS FOR 'admin'@'localhost';
+---------------------------------------------+
| Grants for admin@localhost |
+---------------------------------------------+
| GRANT PROCESS ON *.* TO 'admin'@'localhost' |
+---------------------------------------------+
Dropping Accounts
To remove an account, use the *note 'DROP USER': drop-user. statement. For example, to drop some of the accounts created previously:
DROP USER 'finley'@'localhost';
DROP USER 'finley'@'%.example.com';
DROP USER 'admin'@'localhost';
DROP USER 'dummy'@'localhost';
File: manual.info.tmp, Node: reserved-accounts, Next: privilege-changes, Prev: creating-accounts, Up: access-control
One part of the MySQL installation process is data directory initialization (see *note data-directory-initialization::). During data directory initialization, MySQL creates user accounts that should be considered reserved:
''root'@'localhost': Used for administrative purposes. This account has all privileges and can perform any operation.
Strictly speaking, this account name is not reserved, in the sense that some installations rename the 'root' account to something else to avoid exposing a highly privileged account with a well-known name.
''mysql.sys'@'localhost'': Used as the 'DEFINER' for *note 'sys': sys-schema. schema objects. Use of the 'mysql.sys' account avoids problems that occur if a DBA renames or removes the 'root' account. This account is locked so that it cannot be used for client connections.
''mysql.session'@'localhost'': Used internally by plugins to access the server. This account is locked so that it cannot be used for client connections.
File: manual.info.tmp, Node: privilege-changes, Next: assigning-passwords, Prev: reserved-accounts, Up: access-control
If the *note 'mysqld': mysqld. server is started without the '--skip-grant-tables' option, it reads all grant table contents into memory during its startup sequence. The in-memory tables become effective for access control at that point.
If you modify the grant tables indirectly using an account-management statement, the server notices these changes and loads the grant tables into memory again immediately. Account-management statements are described in note account-management-statements::. Examples include note 'GRANT': grant, note 'REVOKE': revoke, note 'SET PASSWORD': set-password, and *note 'RENAME USER': rename-user.
If you modify the grant tables directly using statements such as note 'INSERT': insert, note 'UPDATE': update, or *note 'DELETE': delete. (which is not recommended), the changes have no effect on privilege checking until you either tell the server to reload the tables or restart it. Thus, if you change the grant tables directly but forget to reload them, the changes have no effect until you restart the server. This may leave you wondering why your changes seem to make no difference!
To tell the server to reload the grant tables, perform a flush-privileges operation. This can be done by issuing a 'FLUSH PRIVILEGES' statement or by executing a note 'mysqladmin flush-privileges': mysqladmin. or note 'mysqladmin reload': mysqladmin. command.
A grant table reload affects privileges for each existing client session as follows:
Table and column privilege changes take effect with the client's next request.
Database privilege changes take effect the next time the client executes a 'USE DB_NAME' statement.
Note:
Client applications may cache the database name; thus, this effect may not be visible to them without actually changing to a different database.
Global privileges and passwords are unaffected for a connected client. These changes take effect only in sessions for subsequent connections.
If the server is started with the '--skip-grant-tables' option, it does not read the grant tables or implement any access control. Any user can connect and perform any operation, which is insecure. To cause a server thus started to read the tables and enable access checking, flush the privileges.
File: manual.info.tmp, Node: assigning-passwords, Next: password-management, Prev: privilege-changes, Up: access-control
Required credentials for clients that connect to the MySQL server can include a password. This section describes how to assign passwords for MySQL accounts.
MySQL stores credentials in the 'user' table in the 'mysql' system database. Operations that assign or modify passwords are permitted only to users with the 'CREATE USER' privilege, or, alternatively, privileges for the 'mysql' database ('INSERT' privilege to create new accounts, 'UPDATE' privilege to modify existing accounts). If the 'read_only' system variable is enabled, use of account-modification statements such as note 'CREATE USER': create-user. or note 'ALTER USER': alter-user. additionally requires the 'SUPER' privilege.
The discussion here summarizes syntax only for the most common password-assignment statements. For complete details on other possibilities, see note create-user::, note alter-user::, note grant::, and note set-password::.
MySQL uses plugins to perform client authentication; see note pluggable-authentication::. In password-assigning statements, the authentication plugin associated with an account performs any hashing required of a cleartext password specified. This enables MySQL to obfuscate passwords prior to storing them in the 'mysql.user' system table. For the statements described here, MySQL automatically hashes the password specified. There are also syntax for note 'CREATE USER': create-user. and *note 'ALTER USER': alter-user. that permits hashed values to be specified literally. For details, see the descriptions of those statements.
To assign a password when you create a new account, use *note 'CREATE USER': create-user. and include an 'IDENTIFIED BY' clause:
CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'PASSWORD';
note 'CREATE USER': create-user. also supports syntax for specifying the account authentication plugin. See note create-user::.
To assign or change a password for an existing account, use the *note 'ALTER USER': alter-user. statement with an 'IDENTIFIED BY' clause:
ALTER USER 'jeffrey'@'localhost' IDENTIFIED BY 'PASSWORD';
If you are not connected as an anonymous user, you can change your own password without naming your own account literally:
ALTER USER USER() IDENTIFIED BY 'PASSWORD';
To change an account password from the command line, use the *note 'mysqladmin': mysqladmin. command:
mysqladmin -u USER_NAME -h HOST_NAME password "PASSWORD"
The account for which this command sets the password is the one with a row in the 'mysql.user' system table that matches USER_NAME in the 'User' column and the client host from which you connect in the 'Host' column.
Warning:
Setting a password using *note 'mysqladmin': mysqladmin. should be considered insecure. On some systems, your password becomes visible to system status programs such as 'ps' that may be invoked by other users to display command lines. MySQL clients typically overwrite the command-line password argument with zeros during their initialization sequence. However, there is still a brief interval during which the value is visible. Also, on some systems this overwriting strategy is ineffective and the password remains visible to 'ps'. (SystemV Unix systems and perhaps others are subject to this problem.)
If you are using MySQL Replication, be aware that, currently, a password used by a replica as part of a *note 'CHANGE MASTER TO': change-master-to. statement is effectively limited to 32 characters in length; if the password is longer, any excess characters are truncated. This is not due to any limit imposed by the MySQL Server generally, but rather is an issue specific to MySQL Replication. (For more information, see Bug #43439.)
File: manual.info.tmp, Node: password-management, Next: expired-password-handling, Prev: assigning-passwords, Up: access-control
MySQL enables database administrators to expire account passwords manually, and to establish a policy for automatic password expiration. Expiration policy can be established globally, and individual accounts can be set to either defer to the global policy or override the global policy with specific per-account behavior.
*note internal-versus-external-credentials::
*note password-expiration-policy::
Internal Versus External Credentials Storage
Some authentication plugins store account credentials internally to MySQL, in the 'mysql.user' system table:
'mysql_native_password'
'sha256_password'
The discussion in this section applies to such authentication plugins because the password-management capabilities described here are based on internal credentials storage handled by MySQL itself.
Other authentication plugins store account credentials externally to MySQL. For accounts that use plugins that perform authentication against an external credentials system, password management must be handled externally against that system as well.
For information about individual authentication plugins, see *note authentication-plugins::.
Password Expiration Policy
To expire an account password manually, use the *note 'ALTER USER': alter-user. statement:
ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE;
This operation marks the password expired in the corresponding 'mysql.user' system table row.
Password expiration according to policy is automatic and is based on password age, which for a given account is assessed from the date and time of its most recent password change. The 'mysql.user' system table indicates for each account when its password was last changed, and the server automatically treats the password as expired at client connection time if its age is greater than its permitted lifetime. This works with no explicit manual password expiration.
To establish automatic password-expiration policy globally, use the 'default_password_lifetime' system variable. Its default value is 0, which disables automatic password expiration. If the value of 'default_password_lifetime' is a positive integer N, it indicates the permitted password lifetime, such that passwords must be changed every N days.
Note:
Prior to 5.7.11, the default 'default_password_lifetime' value is 360 (passwords must be changed approximately once per year). For such versions, be aware that, if you make no changes to the 'default_password_lifetime' variable or to individual user accounts, each user password expires after 360 days and the account starts running in restricted mode. Clients that connect to the server using the account then get an error indicating that the password must be changed: 'ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.'
However, this is easy to miss for clients that automatically connect to the server, such as connections made from scripts. To avoid having such clients suddenly stop working due to a password expiring, make sure to change the password expiration settings for those clients, like this:
ALTER USER 'script'@'localhost' PASSWORD EXPIRE NEVER
Alternatively, set the 'default_password_lifetime' variable to '0', thus disabling automatic password expiration for all users.
Examples:
To establish a global policy that passwords have a lifetime of approximately six months, start the server with these lines in a server 'my.cnf' file:
[mysqld]
default_password_lifetime=180
To establish a global policy such that passwords never expire, set 'default_password_lifetime' to 0:
[mysqld]
default_password_lifetime=0
'default_password_lifetime' can also be changed at runtime:
SET GLOBAL default_password_lifetime = 180;
SET GLOBAL default_password_lifetime = 0;
The global password-expiration policy applies to all accounts that have not been set to override it. To establish policy for individual accounts, use the 'PASSWORD EXPIRE' options of the note 'CREATE USER': create-user. and note 'ALTER USER': alter-user. statements. See note create-user::, and note alter-user::.
Example account-specific statements:
Require the password to be changed every 90 days:
CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
This expiration option overrides the global policy for all accounts named by the statement.
Disable password expiration:
CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE NEVER;
ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE NEVER;
This expiration option overrides the global policy for all accounts named by the statement.
Defer to the global expiration policy for all accounts named by the statement:
CREATE USER 'jeffrey'@'localhost' PASSWORD EXPIRE DEFAULT;
ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE DEFAULT;
When a client successfully connects, the server determines whether the account password has expired:
The server checks whether the password has been manually expired.
Otherwise, the server checks whether the password age is greater than its permitted lifetime according to the automatic password expiration policy. If so, the server considers the password expired.
If the password is expired (whether manually or automatically), the server either disconnects the client or restricts the operations permitted to it (see *note expired-password-handling::). Operations performed by a restricted client result in an error until the user establishes a new account password:
mysql> SELECT 1;
ERROR 1820 (HY000): You must reset your password using ALTER USER
statement before executing this statement.
mysql> ALTER USER USER() IDENTIFIED BY 'PASSWORD';
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
This restricted mode of operation permits note 'SET': set-variable. statements, which is useful before MySQL 5.7.6 if note 'SET PASSWORD': set-password. must be used instead of *note 'ALTER USER': alter-user. and the account password has a hashing format that requires 'old_passwords' to be set to a value different from its default.
After the client resets the password, the server restores normal access for the session, as well as for subsequent connections that use the account. It is also possible for an administrative user to reset the account password, but any existing restricted sessions for that account remain restricted. A client using the account must disconnect and reconnect before statements can be executed successfully.
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.
File: manual.info.tmp, Node: expired-password-handling, Next: pluggable-authentication, Prev: password-management, Up: access-control
MySQL provides password-expiration capability, which enables database administrators to require that users reset their password. Passwords can be expired manually, and on the basis of a policy for automatic expiration (see *note password-management::).
The *note 'ALTER USER': alter-user. statement enables account password expiration. For example:
ALTER USER 'myuser'@'localhost' PASSWORD EXPIRE;
For each connection that uses an account with an expired password, the server either disconnects the client or restricts the client to 'sandbox mode,' in which the server permits the client to perform only those operations necessary to reset the expired password. Which action is taken by the server depends on both client and server settings, as discussed later.
If the server disconnects the client, it returns an 'ER_MUST_CHANGE_PASSWORD_LOGIN' (https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_must_change_password_login) error:
$> mysql -u myuser -p
Password: ******
ERROR 1862 (HY000): Your password has expired. To log in you must
change it using a client that supports expired passwords.
If the server restricts the client to sandbox mode, these operations are permitted within the client session:
The client can reset the account password with note 'ALTER USER': alter-user. or note 'SET PASSWORD': set-password. After that has been done, the server restores normal access for the session, as well as for subsequent connections that use the account.
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.
The client can use the note 'SET': set-variable. statement, which is useful before MySQL 5.7.6 if note 'SET PASSWORD': set-password. must be used instead of *note 'ALTER USER': alter-user. and the account uses an authentication plugin for which the 'old_passwords' system variable must first be set to a nondefault value to perform password hashing in a specific way.
For any operation not permitted within the session, the server returns an 'ER_MUST_CHANGE_PASSWORD' (https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_must_change_password) error:
mysql> USE performance_schema;
ERROR 1820 (HY000): You must reset your password using ALTER USER
statement before executing this statement.
mysql> SELECT 1;
ERROR 1820 (HY000): You must reset your password using ALTER USER
statement before executing this statement.
That is what normally happens for interactive invocations of the *note 'mysql': mysql. client because by default such invocations are put in sandbox mode. To resume normal functioning, select a new password.
For noninteractive invocations of the note 'mysql': mysql. client (for example, in batch mode), the server normally disconnects the client if the password is expired. To permit noninteractive note 'mysql': mysql. invocations to stay connected so that the password can be changed (using the statements permitted in sandbox mode), add the '--connect-expired-password' option to the *note 'mysql': mysql. command.
As mentioned previously, whether the server disconnects an expired-password client or restricts it to sandbox mode depends on a combination of client and server settings. The following discussion describes the relevant settings and how they interact.
Note:
This discussion applies only for accounts with expired passwords. If a client connects using a nonexpired password, the server handles the client normally.
On the client side, a given client indicates whether it can handle sandbox mode for expired passwords. For clients that use the C client library, there are two ways to do this:
Pass the 'MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS' flag to 'mysql_options()' (https://dev.mysql.com/doc/c-api/5.7/en/mysql-options.html) prior to connecting:
my_bool arg = 1;
mysql_options(mysql,
MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
&arg);
This is the technique used within the *note 'mysql': mysql. client, which enables 'MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS' if invoked interactively or with the '--connect-expired-password' option.
Pass the 'CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS' flag to 'mysql_real_connect()' (https://dev.mysql.com/doc/c-api/5.7/en/mysql-real-connect.html) at connect time:
MYSQL mysql;
mysql_init(&mysql);
if (!mysql_real_connect(&mysql,
host, user, password, db,
port, unix_socket,
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS))
{
... handle error ...
}
Other MySQL Connectors have their own conventions for indicating readiness to handle sandbox mode. See the documentation for the Connector in which you are interested.
On the server side, if a client indicates that it can handle expired passwords, the server puts it in sandbox mode.
If a client does not indicate that it can handle expired passwords (or uses an older version of the client library that cannot so indicate), the server action depends on the value of the 'disconnect_on_expired_password' system variable:
If 'disconnect_on_expired_password' is enabled (the default), the server disconnects the client with an 'ER_MUST_CHANGE_PASSWORD_LOGIN' (https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_must_change_password_login) error.
If 'disconnect_on_expired_password' is disabled, the server puts the client in sandbox mode.
File: manual.info.tmp, Node: pluggable-authentication, Next: proxy-users, Prev: expired-password-handling, Up: access-control
When a client connects to the MySQL server, the server uses the user name provided by the client and the client host to select the appropriate account row from the 'mysql.user' system table. The server then authenticates the client, determining from the account row which authentication plugin applies to the client:
If the server cannot find the plugin, an error occurs and the connection attempt is rejected.
Otherwise, the server invokes that plugin to authenticate the user, and the plugin returns a status to the server indicating whether the user provided the correct password and is permitted to connect.
Pluggable authentication enables these important capabilities:
Choice of authentication methods
Pluggable authentication makes it easy for DBAs to choose and change the authentication method used for individual MySQL accounts.
External authentication
Pluggable authentication makes it possible for clients to connect to the MySQL server with credentials appropriate for authentication methods that store credentials elsewhere than in the 'mysql.user' system table. For example, plugins can be created to use external authentication methods such as PAM, Windows login IDs, LDAP, or Kerberos.
Proxy users:
If a user is permitted to connect, an authentication plugin can return to the server a user name different from the name of the connecting user, to indicate that the connecting user is a proxy for another user (the proxied user). While the connection lasts, the proxy user is treated, for purposes of access control, as having the privileges of the proxied user. In effect, one user impersonates another. For more information, see *note proxy-users::.
Note:
If you start the server with the '--skip-grant-tables' option, authentication plugins are not used even if loaded because the server performs no client authentication and permits any client to connect. Because this is insecure, you might want to use '--skip-grant-tables' in conjunction with enabling the 'skip_networking' system variable to prevent remote clients from connecting.
*note pluggable-authentication-available-plugins::
*note pluggable-authentication-usage::
*note pluggable-authentication-restrictions::
Available Authentication Plugins
MySQL 5.7 provides these authentication plugins:
Plugins that perform native authentication; that is, authentication based on the password hashing methods in use from before the introduction of pluggable authentication in MySQL. The 'mysql_native_password' plugin implements authentication based on the native password hashing method. The 'mysql_old_password' plugin implements native authentication based on the older (pre-4.1) password hashing method (and is deprecated and removed in MySQL 5.7.5). See note native-pluggable-authentication::, and note old-native-pluggable-authentication::.
Plugins that perform authentication using SHA-256 password hashing. This is stronger encryption than that available with native authentication. See note sha256-pluggable-authentication::, and note caching-sha2-pluggable-authentication::.
A client-side plugin that sends the password to the server without hashing or encryption. This plugin is used in conjunction with server-side plugins that require access to the password exactly as provided by the client user. See *note cleartext-pluggable-authentication::.
A plugin that performs external authentication using PAM (Pluggable Authentication Modules), enabling MySQL Server to use PAM to authenticate MySQL users. This plugin supports proxy users as well. See *note pam-pluggable-authentication::.
A plugin that performs external authentication on Windows, enabling MySQL Server to use native Windows services to authenticate client connections. Users who have logged in to Windows can connect from MySQL client programs to the server based on the information in their environment without specifying an additional password. This plugin supports proxy users as well. See *note windows-pluggable-authentication::.
Plugins that perform authentication using LDAP (Lightweight Directory Access Protocol) to authenticate MySQL users by accessing directory services such as X.500. These plugins support proxy users as well. See *note ldap-pluggable-authentication::.
A plugin that prevents all client connections to any account that uses it. Use cases for this plugin include proxied accounts that should never permit direct login but are accessed only through proxy accounts and accounts that must be able to execute stored programs and views with elevated privileges without exposing those privileges to ordinary users. See *note no-login-pluggable-authentication::.
A plugin that authenticates clients that connect from the local host through the Unix socket file. See *note socket-pluggable-authentication::.
A test plugin that checks account credentials and logs success or failure to the server error log. This plugin is intended for testing and development purposes, and as an example of how to write an authentication plugin. See *note test-pluggable-authentication::.
Note:
For information about current restrictions on the use of pluggable authentication, including which connectors support which plugins, see *note pluggable-authentication-restrictions::.
Third-party connector developers should read that section to determine the extent to which a connector can take advantage of pluggable authentication capabilities and what steps to take to become more compliant.
If you are interested in writing your own authentication plugins, see Writing Authentication Plugins (https://dev.mysql.com/doc/extending-mysql/5.7/en/writing-authentication-plugins.html).
Authentication Plugin Usage
This section provides general instructions for installing and using authentication plugins. For instructions specific to a given plugin, see the section that describes that plugin under *note authentication-plugins::.
In general, pluggable authentication uses a pair of corresponding plugins on the server and client sides, so you use a given authentication method like this:
If necessary, install the plugin library or libraries containing the appropriate plugins. On the server host, install the library containing the server-side plugin, so that the server can use it to authenticate client connections. Similarly, on each client host, install the library containing the client-side plugin for use by client programs. Authentication plugins that are built in need not be installed.
For each MySQL account that you create, specify the appropriate server-side plugin to use for authentication. If the account is to use the default authentication plugin, the account-creation statement need not specify the plugin explicitly. The 'default_authentication_plugin' system variable configures the default authentication plugin.
When a client connects, the server-side plugin tells the client program which client-side plugin to use for authentication.
In the case that an account uses an authentication method that is the default for both the server and the client program, the server need not communicate to the client which client-side plugin to use, and a round trip in client/server negotiation can be avoided. This is true for accounts that use native MySQL authentication.
For standard MySQL clients such as note 'mysql': mysql. and note 'mysqladmin': mysqladmin, the '--default-auth=PLUGIN_NAME' option can be specified on the command line as a hint about which client-side plugin the program can expect to use, although the server overrides this if the server-side plugin associated with the user account requires a different client-side plugin.
If the client program does not find the client-side plugin library file, specify a '--plugin-dir=DIR_NAME' option to indicate the plugin library directory location.
Restrictions on Pluggable Authentication
The first part of this section describes general restrictions on the applicability of the pluggable authentication framework described at *note pluggable-authentication::. The second part describes how third-party connector developers can determine the extent to which a connector can take advantage of pluggable authentication capabilities and what steps to take to become more compliant.
The term 'native authentication' used here refers to authentication against passwords stored in the 'mysql.user' system table. This is the same authentication method provided by older MySQL servers, before pluggable authentication was implemented. 'Windows native authentication' refers to authentication using the credentials of a user who has already logged in to Windows, as implemented by the Windows Native Authentication plugin ('Windows plugin' for short).
*note pluggable-authentication-restrictions-general::
*note pluggable-authentication-restrictions-third-party-connectors::
General Pluggable Authentication Restrictions
Connector/C++: Clients that use this connector can connect to the server only through accounts that use native authentication.
Exception: A connector supports pluggable authentication if it was built to link to 'libmysqlclient' dynamically (rather than statically) and it loads the current version of 'libmysqlclient' if that version is installed, or if the connector is recompiled from source to link against the current 'libmysqlclient'.
Connector/NET: Clients that use Connector/NET can connect to the server through accounts that use native authentication or Windows native authentication.
Connector/PHP: Clients that use this connector can connect to the server only through accounts that use native authentication, when compiled using the MySQL native driver for PHP ('mysqlnd').
Windows native authentication: Connecting through an account that uses the Windows plugin requires Windows Domain setup. Without it, NTLM authentication is used and then only local connections are possible; that is, the client and server must run on the same computer.
Proxy users: Proxy user support is available to the extent that clients can connect through accounts authenticated with plugins that implement proxy user capability (that is, plugins that can return a user name different from that of the connecting user). For example, the PAM and Windows plugins support proxy users. The 'mysql_native_password' and 'sha256_password' authentication plugins do not support proxy users by default, but can be configured to do so; see *note proxy-users-server-user-mapping::.
Replication: Replicas can employ not only source accounts using native authentication, but can also connect through source accounts that use nonnative authentication if the required client-side plugin is available. If the plugin is built into 'libmysqlclient', it is available by default. Otherwise, the plugin must be installed on the replica side in the directory named by the replica 'plugin_dir' system variable.
**note 'FEDERATED': federated-storage-engine. tables:* A *note 'FEDERATED': federated-storage-engine. table can access the remote table only through accounts on the remote server that use native authentication.
Pluggable Authentication and Third-Party Connectors
Third-party connector developers can use the following guidelines to determine readiness of a connector to take advantage of pluggable authentication capabilities and what steps to take to become more compliant:
An existing connector to which no changes have been made uses native authentication and clients that use the connector can connect to the server only through accounts that use native authentication. However, you should test the connector against a recent version of the server to verify that such connections still work without problem.
Exception: A connector might work with pluggable authentication without any changes if it links to 'libmysqlclient' dynamically (rather than statically) and it loads the current version of 'libmysqlclient' if that version is installed.
To take advantage of pluggable authentication capabilities, a connector that is 'libmysqlclient'-based should be relinked against the current version of 'libmysqlclient'. This enables the connector to support connections though accounts that require client-side plugins now built into 'libmysqlclient' (such as the cleartext plugin needed for PAM authentication and the Windows plugin needed for Windows native authentication). Linking with a current 'libmysqlclient' also enables the connector to access client-side plugins installed in the default MySQL plugin directory (typically the directory named by the default value of the local server's 'plugin_dir' system variable).
If a connector links to 'libmysqlclient' dynamically, it must be ensured that the newer version of 'libmysqlclient' is installed on the client host and that the connector loads it at runtime.
Another way for a connector to support a given authentication method is to implement it directly in the client/server protocol. Connector/NET uses this approach to provide support for Windows native authentication.
If a connector should be able to load client-side plugins from a directory different from the default plugin directory, it must implement some means for client users to specify the directory. Possibilities for this include a command-line option or environment variable from which the connector can obtain the directory name. Standard MySQL client programs such as note 'mysql': mysql. and note 'mysqladmin': mysqladmin. implement a '--plugin-dir' option. See also C API Client Plugin Interface (https://dev.mysql.com/doc/c-api/5.7/en/c-api-plugin-interface.html).
Proxy user support by a connector depends, as described earlier in this section, on whether the authentication methods that it supports permit proxy users.
File: manual.info.tmp, Node: proxy-users, Next: account-locking, Prev: pluggable-authentication, Up: access-control
The MySQL server authenticates client connections using authentication plugins. The plugin that authenticates a given connection may request that the connecting (external) user be treated as a different user for privilege-checking purposes. This enables the external user to be a proxy for the second user; that is, to assume the privileges of the second user:
The external user is a 'proxy user' (a user who can impersonate or become known as another user).
The second user is a 'proxied user' (a user whose identity and privileges can be assumed by a proxy user).
This section describes how the proxy user capability works. For general information about authentication plugins, see note pluggable-authentication::. For information about specific plugins, see note authentication-plugins::. For information about writing authentication plugins that support proxy users, see Implementing Proxy User Support in Authentication Plugins (https://dev.mysql.com/doc/extending-mysql/5.7/en/writing-authentication-plugins-proxy-users.html).
*note proxy-users-support-requirements::
*note proxy-users-example::
*note preventing-proxied-account-direct-login::
*note proxy-users-granting-proxy-privilege::
*note default-proxy-users::
*note proxy-users-conflicts::
*note proxy-users-server-user-mapping::
*note proxy-users-system-variables::
Requirements for Proxy User Support
For proxying to occur for a given authentication plugin, these conditions must be satisfied:
Proxying must be supported, either by the plugin itself, or by the MySQL server on behalf of the plugin. In the latter case, server support may need to be enabled explicitly; see *note proxy-users-server-user-mapping::.
The account for the external proxy user must be set up to be authenticated by the plugin. Use the note 'CREATE USER': create-user. statement to associate an account with an authentication plugin, or note 'ALTER USER': alter-user. to change its plugin.
The account for the proxied user must exist and be granted the privileges to be assumed by the proxy user. Use the note 'CREATE USER': create-user. and note 'GRANT': grant. statements for this.
Normally, the proxied user is configured so that it can be used only in proxying scenaries and not for direct logins.
The proxy user account must have the 'PROXY' privilege for the proxied account. Use the *note 'GRANT': grant. statement for this.
For a client connecting to the proxy account to be treated as a proxy user, the authentication plugin must return a user name different from the client user name, to indicate the user name of the proxied account that defines the privileges to be assumed by the proxy user.
Alternatively, for plugins that are provided proxy mapping by the server, the proxied user is determined from the 'PROXY' privilege held by the proxy user.
The proxy mechanism permits mapping only the external client user name to the proxied user name. There is no provision for mapping host names:
When a client connects to the server, the server determines the proper account based on the user name passed by the client program and the host from which the client connects.
If that account is a proxy account, the server attempts to determine the appropriate proxied account by finding a match for a proxied account using the user name returned by the authentication plugin and the host name of the proxy account. The host name in the proxied account is ignored.
Simple Proxy User Example
Consider the following account definitions:
-- create proxy account
CREATE USER 'employee_ext'@'localhost'
IDENTIFIED WITH my_auth_plugin
AS 'MY_AUTH_STRING';
-- create proxied account and grant its privileges;
-- use mysql_no_login plugin to prevent direct login
CREATE USER 'employee'@'localhost'
IDENTIFIED WITH mysql_no_login;
GRANT ALL
ON employees.*
TO 'employee'@'localhost';
-- grant to proxy account the
-- PROXY privilege for proxied account
GRANT PROXY
ON 'employee'@'localhost'
TO 'employee_ext'@'localhost';
When a client connects as 'employee_ext' from the local host, MySQL uses the plugin named 'my_auth_plugin' to perform authentication. Suppose that 'my_auth_plugin' returns a user name of 'employee' to the server, based on the content of ''MY_AUTH_STRING'' and perhaps by consulting some external authentication system. The name 'employee' differs from 'employee_ext', so returning 'employee' serves as a request to the server to treat the 'employee_ext' external user, for purposes of privilege checking, as the 'employee' local user.
In this case, 'employee_ext' is the proxy user and 'employee' is the proxied user.
The server verifies that proxy authentication for 'employee' is possible for the 'employee_ext' user by checking whether 'employee_ext' (the proxy user) has the 'PROXY' privilege for 'employee' (the proxied user). If this privilege has not been granted, an error occurs. Otherwise, 'employee_ext' assumes the privileges of 'employee'. The server checks statements executed during the client session by 'employee_ext' against the privileges granted to 'employee'. In this case, 'employee_ext' can access tables in the 'employees' database.
The proxied account, 'employee', uses the 'mysql_no_login' authentication plugin to prevent clients from using the account to log in directly. (This assumes that the plugin is installed. For instructions, see note no-login-pluggable-authentication::.) For alternative methods of protecting proxied accounts against direct use, see note preventing-proxied-account-direct-login::.
When proxying occurs, the 'USER()' and 'CURRENT_USER()' functions can be used to see the difference between the connecting user (the proxy user) and the account whose privileges apply during the current session (the proxied user). For the example just described, those functions return these values:
mysql> SELECT USER(), CURRENT_USER();
+------------------------+--------------------+
| USER() | CURRENT_USER() |
+------------------------+--------------------+
| employee_ext@localhost | employee@localhost |
+------------------------+--------------------+
In the *note 'CREATE USER': create-user. statement that creates the proxy user account, the 'IDENTIFIED WITH' clause that names the proxy-supporting authentication plugin is optionally followed by an 'AS 'AUTH_STRING'' clause specifying a string that the server passes to the plugin when the user connects. If present, the string provides information that helps the plugin determine how to map the proxy (external) client user name to a proxied user name. It is up to each plugin whether it requires the 'AS' clause. If so, the format of the authentication string depends on how the plugin intends to use it. Consult the documentation for a given plugin for information about the authentication string values it accepts.
Preventing Direct Login to Proxied Accounts
Proxied accounts generally are intended to be used only by means of proxy accounts. That is, clients connect using a proxy account, then are mapped onto and assume the privileges of the appropriate proxied user.
There are multiple ways to ensure that a proxied account cannot be used directly:
Associate the account with the 'mysql_no_login' authentication plugin. In this case, the account cannot be used for direct logins under any circumstances. This assumes that the plugin is installed. For instructions, see *note no-login-pluggable-authentication::.
Include the 'ACCOUNT LOCK' option when you create the account. See note create-user::. With this method, also include a password so that if the account is unlocked later, it cannot be accessed with no password. (If the 'validate_password' plugin is enabled, it does not permit creating an account without a password, even if the account is locked. See note validate-password::.)
Create the account with a password but do not tell anyone else the password. If you do not let anyone know the password for the account, clients cannot use it to connect directly to the MySQL server.
Granting and Revoking the PROXY Privilege
The 'PROXY' privilege is needed to enable an external user to connect as and have the privileges of another user. To grant this privilege, use the *note 'GRANT': grant. statement. For example:
GRANT PROXY ON 'PROXIED_USER' TO 'PROXY_USER';
The statement creates a row in the 'mysql.proxies_priv' grant table.
At connect time, PROXY_USER must represent a valid externally authenticated MySQL user, and PROXIED_USER must represent a valid locally authenticated user. Otherwise, the connection attempt fails.
The corresponding *note 'REVOKE': revoke. syntax is:
REVOKE PROXY ON 'PROXIED_USER' FROM 'PROXY_USER';
MySQL note 'GRANT': grant. and note 'REVOKE': revoke. syntax extensions work as usual. Examples:
-- grant PROXY to multiple accounts
GRANT PROXY ON 'a' TO 'b', 'c', 'd';
-- revoke PROXY from multiple accounts
REVOKE PROXY ON 'a' FROM 'b', 'c', 'd';
-- grant PROXY to an account and enable the account to grant
-- PROXY to the proxied account
GRANT PROXY ON 'a' TO 'd' WITH GRANT OPTION;
-- grant PROXY to default proxy account
GRANT PROXY ON 'a' TO ''@'';
The 'PROXY' privilege can be granted in these cases:
By a user that has 'GRANT PROXY ... WITH GRANT OPTION' for PROXIED_USER.
By PROXIED_USER for itself: The value of 'USER()' must exactly match 'CURRENT_USER()' and PROXIED_USER, for both the user name and host name parts of the account name.
The initial 'root' account created during MySQL installation has the 'PROXY ... WITH GRANT OPTION' privilege for '''@''', that is, for all users and all hosts. This enables 'root' to set up proxy users, as well as to delegate to other accounts the authority to set up proxy users. For example, 'root' can do this:
CREATE USER 'admin'@'localhost'
IDENTIFIED BY 'ADMIN_PASSWORD';
GRANT PROXY
ON ''@''
TO 'admin'@'localhost'
WITH GRANT OPTION;
Those statements create an 'admin' user that can manage all 'GRANT PROXY' mappings. For example, 'admin' can do this:
GRANT PROXY ON sally TO joe;
Default Proxy Users
To specify that some or all users should connect using a given authentication plugin, create a 'blank' MySQL account with an empty user name and host name ('''@'''), associate it with that plugin, and let the plugin return the real authenticated user name (if different from the blank user). Suppose that there exists a plugin named 'ldap_auth' that implements LDAP authentication and maps connecting users onto either a developer or manager account. To set up proxying of users onto these accounts, use the following statements:
-- create default proxy account
CREATE USER ''@''
IDENTIFIED WITH ldap_auth
AS 'O=Oracle, OU=MySQL';
-- create proxied accounts; use
-- mysql_no_login plugin to prevent direct login
CREATE USER 'developer'@'localhost'
IDENTIFIED WITH mysql_no_login;
CREATE USER 'manager'@'localhost'
IDENTIFIED WITH mysql_no_login;
-- grant to default proxy account the
-- PROXY privilege for proxied accounts
GRANT PROXY
ON 'manager'@'localhost'
TO ''@'';
GRANT PROXY
ON 'developer'@'localhost'
TO ''@'';
Now assume that a client connects as follows:
$> mysql --user=myuser --password ...
Enter password: MYUSER_PASSWORD
The server does not find 'myuser' defined as a MySQL user, but because there is a blank user account ('''@''') that matches the client user name and host name, the server authenticates the client against that account: The server invokes the 'ldap_auth' authentication plugin and passes 'myuser' and MYUSER_PASSWORD to it as the user name and password.
If the 'ldap_auth' plugin finds in the LDAP directory that MYUSER_PASSWORD is not the correct password for 'myuser', authentication fails and the server rejects the connection.
If the password is correct and 'ldap_auth' finds that 'myuser' is a developer, it returns the user name 'developer' to the MySQL server, rather than 'myuser'. Returning a user name different from the client user name of 'myuser' signals to the server that it should treat 'myuser' as a proxy. The server verifies that '''@''' can authenticate as 'developer' (because '''@''' has the 'PROXY' privilege to do so) and accepts the connection. The session proceeds with 'myuser' having the privileges of the 'developer' proxied user. (These privileges should be set up by the DBA using *note 'GRANT': grant. statements, not shown.) The 'USER()' and 'CURRENT_USER()' functions return these values:
mysql> SELECT USER(), CURRENT_USER();
+------------------+---------------------+
| USER() | CURRENT_USER() |
+------------------+---------------------+
| myuser@localhost | developer@localhost |
+------------------+---------------------+
If the plugin instead finds in the LDAP directory that 'myuser' is a manager, it returns 'manager' as the user name and the session proceeds with 'myuser' having the privileges of the 'manager' proxied user.
mysql> SELECT USER(), CURRENT_USER();
+------------------+-------------------+
| USER() | CURRENT_USER() |
+------------------+-------------------+
| myuser@localhost | manager@localhost |
+------------------+-------------------+
For simplicity, external authentication cannot be multilevel: Neither the credentials for 'developer' nor those for 'manager' are taken into account in the preceding example. However, they are still used if a client tries to connect and authenticate directly as the 'developer' or 'manager' account, which is why those proxied accounts should be protected against direct login (see *note preventing-proxied-account-direct-login::).
Default Proxy User and Anonymous User Conflicts
If you intend to create a default proxy user, check for other existing 'match any user' accounts that take precedence over the default proxy user because they can prevent that user from working as intended.
In the preceding discussion, the default proxy user account has '''' in the host part, which matches any host. If you set up a default proxy user, take care to also check whether nonproxy accounts exist with the same user part and ''%'' in the host part, because ''%'' also matches any host, but has precedence over '''' by the rules that the server uses to sort account rows internally (see *note connection-access::).
Suppose that a MySQL installation includes these two accounts:
-- create default proxy account
CREATE USER ''@''
IDENTIFIED WITH some_plugin
AS 'SOME_AUTH_STRING';
-- create anonymous account
CREATE USER ''@'%'
IDENTIFIED BY 'ANON_USER_PASSWORD';
The first account ('''@''') is intended as the default proxy user, used to authenticate connections for users who do not otherwise match a more-specific account. The second account ('''@'%'') is an anonymous-user account, which might have been created, for example, to enable users without their own account to connect anonymously.
Both accounts have the same user part (''''), which matches any user. And each account has a host part that matches any host. Nevertheless, there is a priority in account matching for connection attempts because the matching rules sort a host of ''%'' ahead of ''''. For accounts that do not match any more-specific account, the server attempts to authenticate them against '''@'%'' (the anonymous user) rather than '''@''' (the default proxy user). As a result, the default proxy account is never used.
To avoid this problem, use one of the following strategies:
Remove the anonymous account so that it does not conflict with the default proxy user.
Use a more-specific default proxy user that matches ahead of the anonymous user. For example, to permit only 'localhost' proxy connections, use '''@'localhost'':
CREATE USER ''@'localhost'
IDENTIFIED WITH some_plugin
AS 'SOME_AUTH_STRING';
In addition, modify any 'GRANT PROXY' statements to name '''@'localhost'' rather than '''@''' as the proxy user.
Be aware that this strategy prevents anonymous-user connections from 'localhost'.
Use a named default account rather than an anonymous default account. For an example of this technique, consult the instructions for using the 'authentication_windows' plugin. See *note windows-pluggable-authentication::.
Create multiple proxy users, one for local connections and one for 'everything else' (remote connections). This can be useful particularly when local users should have different privileges from remote users.
Create the proxy users:
-- create proxy user for local connections
CREATE USER ''@'localhost'
IDENTIFIED WITH some_plugin
AS 'SOME_AUTH_STRING';
-- create proxy user for remote connections
CREATE USER ''@'%'
IDENTIFIED WITH some_plugin
AS 'SOME_AUTH_STRING';
Create the proxied users:
-- create proxied user for local connections
CREATE USER 'developer'@'localhost'
IDENTIFIED WITH mysql_no_login;
-- create proxied user for remote connections
CREATE USER 'developer'@'%'
IDENTIFIED WITH mysql_no_login;
Grant to each proxy account the 'PROXY' privilege for the corresponding proxied account:
GRANT PROXY
ON 'developer'@'localhost'
TO ''@'localhost';
GRANT PROXY
ON 'developer'@'%'
TO ''@'%';
Finally, grant appropriate privileges to the local and remote proxied users (not shown).
Assume that the 'some_plugin'/''SOME_AUTH_STRING'' combination causes 'some_plugin' to map the client user name to 'developer'. Local connections match the '''@'localhost'' proxy user, which maps to the ''developer'@'localhost'' proxied user. Remote connections match the '''@'%'' proxy user, which maps to the ''developer'@'%'' proxied user.
Server Support for Proxy User Mapping
Some authentication plugins implement proxy user mapping for themselves (for example, the PAM and Windows authentication plugins). Other authentication plugins do not support proxy users by default. Of these, some can request that the MySQL server itself map proxy users according to granted proxy privileges: 'mysql_native_password', 'sha256_password'. If the 'check_proxy_users' system variable is enabled, the server performs proxy user mapping for any authentication plugins that make such a request:
By default, 'check_proxy_users' is disabled, so the server performs no proxy user mapping even for authentication plugins that request server support for proxy users.
If 'check_proxy_users' is enabled, it may also be necessary to enable a plugin-specific system variable to take advantage of server proxy user mapping support:
* For the 'mysql_native_password' plugin, enable
'mysql_native_password_proxy_users'.
* For the 'sha256_password' plugin, enable
'sha256_password_proxy_users'.
For example, to enable all the preceding capabilities, start the server with these lines in the 'my.cnf' file:
[mysqld]
check_proxy_users=ON
mysql_native_password_proxy_users=ON
sha256_password_proxy_users=ON
Assuming that the relevant system variables have been enabled, create the proxy user as usual using *note 'CREATE USER': create-user, then grant it the 'PROXY' privilege to a single other account to be treated as the proxied user. When the server receives a successful connection request for the proxy user, it finds that the user has the 'PROXY' privilege and uses it to determine the proper proxied user.
-- create proxy account
CREATE USER 'proxy_user'@'localhost'
IDENTIFIED WITH mysql_native_password
BY 'PASSWORD';
-- create proxied account and grant its privileges;
-- use mysql_no_login plugin to prevent direct login
CREATE USER 'proxied_user'@'localhost'
IDENTIFIED WITH mysql_no_login;
-- grant privileges to proxied account
GRANT ...
ON ...
TO 'proxied_user'@'localhost';
-- grant to proxy account the
-- PROXY privilege for proxied account
GRANT PROXY
ON 'proxied_user'@'localhost'
TO 'proxy_user'@'localhost';
To use the proxy account, connect to the server using its name and password:
$> mysql -u proxy_user -p
Enter password: (ENTER PROXY_USER PASSWORD HERE)
Authentication succeeds, the server finds that 'proxy_user' has the 'PROXY' privilege for 'proxied_user', and the session proceeds with 'proxy_user' having the privileges of 'proxied_user'.
Proxy user mapping performed by the server is subject to these restrictions:
The server does not proxy to or from an anonymous user, even if the associated 'PROXY' privilege is granted.
When a single account has been granted proxy privileges for more than one proxied account, server proxy user mapping is nondeterministic. Therefore, granting to a single account proxy privileges for multiple proxied accounts is discouraged.
Proxy User System Variables
Two system variables help trace the proxy login process:
'proxy_user': This value is 'NULL' if proxying is not used. Otherwise, it indicates the proxy user account. For example, if a client authenticates through the '''@''' proxy account, this variable is set as follows:
mysql> SELECT @@proxy_user;
+--------------+
| @@proxy_user |
+--------------+
| ''@'' |
+--------------+
'external_user': Sometimes the authentication plugin may use an external user to authenticate to the MySQL server. For example, when using Windows native authentication, a plugin that authenticates using the windows API does not need the login ID passed to it. However, it still uses a Windows user ID to authenticate. The plugin may return this external user ID (or the first 512 UTF-8 bytes of it) to the server using the 'external_user' read-only session variable. If the plugin does not set this variable, its value is 'NULL'.
File: manual.info.tmp, Node: account-locking, Next: user-resources, Prev: proxy-users, Up: access-control
MySQL supports locking and unlocking user accounts using the 'ACCOUNT LOCK' and 'ACCOUNT UNLOCK' clauses for the note 'CREATE USER': create-user. and note 'ALTER USER': alter-user. statements:
When used with *note 'CREATE USER': create-user, these clauses specify the initial locking state for a new account. In the absence of either clause, the account is created in an unlocked state.
If the 'validate_password' plugin is enabled, it does not permit creating an account without a password, even if the account is locked. See *note validate-password::.
When used with *note 'ALTER USER': alter-user, these clauses specify the new locking state for an existing account. In the absence of either clause, the account locking state remains unchanged.
Account locking state is recorded in the 'account_locked' column of the 'mysql.user' system table. The output from *note 'SHOW CREATE USER': show-create-user. indicates whether an account is locked or unlocked.
If a client attempts to connect to a locked account, the attempt fails. The server increments the 'Locked_connects' status variable that indicates the number of attempts to connect to a locked account, returns an 'ER_ACCOUNT_HAS_BEEN_LOCKED' (https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_account_has_been_locked) error, and writes a message to the error log:
Access denied for user 'USER_NAME'@'HOST_NAME'.
Account is locked.
Locking an account does not affect being able to connect using a proxy user that assumes the identity of the locked account. It also does not affect the ability to execute stored programs or views that have a 'DEFINER' attribute naming the locked account. That is, the ability to use a proxied account or stored programs or views is not affected by locking the account.
The account-locking capability depends on the presence of the 'account_locked' column in the 'mysql.user' system table. For upgrades from MySQL versions older than 5.7.6, perform the MySQL upgrade procedure to ensure that this column exists. See *note upgrading::. For nonupgraded installations that have no 'account_locked' column, the server treats all accounts as unlocked, and using the 'ACCOUNT LOCK' or 'ACCOUNT UNLOCK' clauses produces an error.
File: manual.info.tmp, Node: user-resources, Next: problems-connecting, Prev: account-locking, Up: access-control
One means of restricting client use of MySQL server resources is to set the global 'max_user_connections' system variable to a nonzero value. This limits the number of simultaneous connections that can be made by any given account, but places no limits on what a client can do once connected. In addition, setting 'max_user_connections' does not enable management of individual accounts. Both types of control are of interest to MySQL administrators.
To address such concerns, MySQL permits limits for individual accounts on use of these server resources:
The number of queries an account can issue per hour
The number of updates an account can issue per hour
The number of times an account can connect to the server per hour
The number of simultaneous connections to the server by an account
Any statement that a client can issue counts against the query limit, unless its results are served from the query cache. Only statements that modify databases or tables count against the update limit.
An 'account' in this context corresponds to a row in the 'mysql.user' system table. That is, a connection is assessed against the 'User' and 'Host' values in the 'user' table row that applies to the connection. For example, an account ''usera'@'%.example.com'' corresponds to a row in the 'user' table that has 'User' and 'Host' values of 'usera' and '%.example.com', to permit 'usera' to connect from any host in the 'example.com' domain. In this case, the server applies resource limits in this row collectively to all connections by 'usera' from any host in the 'example.com' domain because all such connections use the same account.
Before MySQL 5.0, an 'account' was assessed against the actual host from which a user connects. This older method of accounting may be selected by starting the server with the '--old-style-user-limits' option. In this case, if 'usera' connects simultaneously from 'host1.example.com' and 'host2.example.com', the server applies the account resource limits separately to each connection. If 'usera' connects again from 'host1.example.com', the server applies the limits for that connection together with the existing connection from that host.
To establish resource limits for an account at account-creation time, use the note 'CREATE USER': create-user. statement. To modify the limits for an existing account, use note 'ALTER USER': alter-user. Provide a 'WITH' clause that names each resource to be limited. The default value for each limit is zero (no limit). For example, to create a new account that can access the 'customer' database, but only in a limited fashion, issue these statements:
mysql> CREATE USER 'francis'@'localhost' IDENTIFIED BY 'frank'
-> WITH MAX_QUERIES_PER_HOUR 20
-> MAX_UPDATES_PER_HOUR 10
-> MAX_CONNECTIONS_PER_HOUR 5
-> MAX_USER_CONNECTIONS 2;
The limit types need not all be named in the 'WITH' clause, but those named can be present in any order. The value for each per-hour limit should be an integer representing a count per hour. For 'MAX_USER_CONNECTIONS', the limit is an integer representing the maximum number of simultaneous connections by the account. If this limit is set to zero, the global 'max_user_connections' system variable value determines the number of simultaneous connections. If 'max_user_connections' is also zero, there is no limit for the account.
To modify limits for an existing account, use an *note 'ALTER USER': alter-user. statement. The following statement changes the query limit for 'francis' to 100:
mysql> ALTER USER 'francis'@'localhost' WITH MAX_QUERIES_PER_HOUR 100;
The statement modifies only the limit value specified and leaves the account otherwise unchanged.
To remove a limit, set its value to zero. For example, to remove the limit on how many times per hour 'francis' can connect, use this statement:
mysql> ALTER USER 'francis'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 0;
As mentioned previously, the simultaneous-connection limit for an account is determined from the 'MAX_USER_CONNECTIONS' limit and the 'max_user_connections' system variable. Suppose that the global 'max_user_connections' value is 10 and three accounts have individual resource limits specified as follows:
ALTER USER 'user1'@'localhost' WITH MAX_USER_CONNECTIONS 0;
ALTER USER 'user2'@'localhost' WITH MAX_USER_CONNECTIONS 5;
ALTER USER 'user3'@'localhost' WITH MAX_USER_CONNECTIONS 20;
'user1' has a connection limit of 10 (the global 'max_user_connections' value) because it has a 'MAX_USER_CONNECTIONS' limit of zero. 'user2' and 'user3' have connection limits of 5 and 20, respectively, because they have nonzero 'MAX_USER_CONNECTIONS' limits.
The server stores resource limits for an account in the 'user' table row corresponding to the account. The 'max_questions', 'max_updates', and 'max_connections' columns store the per-hour limits, and the 'max_user_connections' column stores the 'MAX_USER_CONNECTIONS' limit. (See *note grant-tables::.)
Resource-use counting takes place when any account has a nonzero limit placed on its use of any of the resources.
As the server runs, it counts the number of times each account uses resources. If an account reaches its limit on number of connections within the last hour, the server rejects further connections for the account until that hour is up. Similarly, if the account reaches its limit on the number of queries or updates, the server rejects further queries or updates until the hour is up. In all such cases, the server issues appropriate error messages.
Resource counting occurs per account, not per client. For example, if your account has a query limit of 50, you cannot increase your limit to 100 by making two simultaneous client connections to the server. Queries issued on both connections are counted together.
The current per-hour resource-use counts can be reset globally for all accounts, or individually for a given account:
To reset the current counts to zero for all accounts, issue a 'FLUSH USER_RESOURCES' statement. The counts also can be reset by reloading the grant tables (for example, with a 'FLUSH PRIVILEGES' statement or a *note 'mysqladmin reload': mysqladmin. command).
The counts for an individual account can be reset to zero by setting any of its limits again. Specify a limit value equal to the value currently assigned to the account.
Per-hour counter resets do not affect the 'MAX_USER_CONNECTIONS' limit.
All counts begin at zero when the server starts. Counts do not carry over through server restarts.
For the 'MAX_USER_CONNECTIONS' limit, an edge case can occur if the account currently has open the maximum number of connections permitted to it: A disconnect followed quickly by a connect can result in an error ('ER_TOO_MANY_USER_CONNECTIONS' (https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_too_many_user_connections) or 'ER_USER_LIMIT_REACHED' (https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_user_limit_reached)) if the server has not fully processed the disconnect by the time the connect occurs. When the server finishes disconnect processing, another connection is once more permitted.
File: manual.info.tmp, Node: problems-connecting, Next: account-activity-auditing, Prev: user-resources, Up: access-control
If you encounter problems when you try to connect to the MySQL server, the following items describe some courses of action you can take to correct the problem.
Make sure that the server is running. If it is not, clients cannot connect to it. For example, if an attempt to connect to the server fails with a message such as one of those following, one cause might be that the server is not running:
$> mysql
ERROR 2003: Can't connect to MySQL server on 'HOST_NAME' (111)
$> mysql
ERROR 2002: Can't connect to local MySQL server through socket
'/tmp/mysql.sock' (111)
It might be that the server is running, but you are trying to connect using a TCP/IP port, named pipe, or Unix socket file different from the one on which the server is listening. To correct this when you invoke a client program, specify a '--port' option to indicate the proper port number, or a '--socket' option to indicate the proper named pipe or Unix socket file. To find out where the socket file is, you can use this command:
$> netstat -ln | grep mysql
Make sure that the server has not been configured to ignore network connections or (if you are attempting to connect remotely) that it has not been configured to listen only locally on its network interfaces. If the server was started with the 'skip_networking' system variable enabled, it does not accept TCP/IP connections at all. If the server was started with the 'bind_address' system variable set to '127.0.0.1', it listens for TCP/IP connections only locally on the loopback interface and does not accept remote connections.
Check to make sure that there is no firewall blocking access to MySQL. Your firewall may be configured on the basis of the application being executed, or the port number used by MySQL for communication (3306 by default). Under Linux or Unix, check your IP tables (or similar) configuration to ensure that the port has not been blocked. Under Windows, applications such as ZoneAlarm or Windows Firewall may need to be configured not to block the MySQL port.
The grant tables must be properly set up so that the server can use them for access control. For some distribution types (such as binary distributions on Windows, or RPM and DEB distributions on Linux), the installation process initializes the MySQL data directory, including the 'mysql' system database containing the grant tables. For distributions that do not do this, you must initialize the data directory manually. For details, see *note postinstallation::.
To determine whether you need to initialize the grant tables, look for a 'mysql' directory under the data directory. (The data directory normally is named 'data' or 'var' and is located under your MySQL installation directory.) Make sure that you have a file named 'user.MYD' in the 'mysql' database directory. If not, *note initialize the data directory: data-directory-initialization. After doing so and starting the server, you should be able to connect to the server.
After a fresh installation, if you try to log on to the server as 'root' without using a password, you might get the following error message.
$> mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
It means a root password has already been assigned during installation and it has to be supplied. See note default-privileges:: on the different ways the password could have been assigned and, in some cases, how to find it. If you need to reset the root password, see instructions in note resetting-permissions::. After you have found or reset your password, log on again as 'root' using the '--password' (or '-p') option:
$> mysql -u root -p
Enter password:
However, the server is going to let you connect as 'root' without using a password if you have initialized MySQL using note 'mysqld --initialize-insecure': mysqld. (see note data-directory-initialization:: for details). That is a security risk, so you should set a password for the 'root' account; see *note default-privileges:: for instructions.
If you have updated an existing MySQL installation to a newer version, did you perform the MySQL upgrade procedure? If not, do so. The structure of the grant tables changes occasionally when new capabilities are added, so after an upgrade you should always make sure that your tables have the current structure. For instructions, see *note upgrading::.
If a client program receives the following error message when it tries to connect, it means that the server expects passwords in a newer format than the client is capable of generating:
$> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client
For information on how to deal with this, see *note account-upgrades::.
Remember that client programs use connection parameters specified in option files or environment variables. If a client program seems to be sending incorrect default connection parameters when you have not specified them on the command line, check any applicable option files and your environment. For example, if you get 'Access denied' when you run a client without any options, make sure that you have not specified an old password in any of your option files!
You can suppress the use of option files by a client program by invoking it with the '--no-defaults' option. For example:
$> mysqladmin --no-defaults -u root version
The option files that clients use are listed in note option-files::. Environment variables are listed in note environment-variables::.
If you get the following error, it means that you are using an incorrect 'root' password:
$> mysqladmin -u root -pXXXX ver
Access denied for user 'root'@'localhost' (using password: YES)
If the preceding error occurs even when you have not specified a password, it means that you have an incorrect password listed in some option file. Try the '--no-defaults' option as described in the previous item.
For information on changing passwords, see *note assigning-passwords::.
If you have lost or forgotten the 'root' password, see *note resetting-permissions::.
'localhost' is a synonym for your local host name, and is also the default host to which clients try to connect if you specify no host explicitly.
You can use a '--host=127.0.0.1' option to name the server host explicitly. This makes a TCP/IP connection to the local *note 'mysqld': mysqld. server. You can also use TCP/IP by specifying a '--host' option that uses the actual host name of the local host. In this case, the host name must be specified in a 'user' table row on the server host, even though you are running the client program on the same host as the server.
The 'Access denied' error message tells you who you are trying to log in as, the client host from which you are trying to connect, and whether you were using a password. Normally, you should have one row in the 'user' table that exactly matches the host name and user name that were given in the error message. For example, if you get an error message that contains 'using password: NO', it means that you tried to log in without a password.
If you get an 'Access denied' error when trying to connect to the database with 'mysql -u USER_NAME', you may have a problem with the 'user' table. Check this by executing 'mysql -u root mysql' and issuing this SQL statement:
SELECT * FROM user;
The result should include a row with the 'Host' and 'User' columns matching your client's host name and your MySQL user name.
If the following error occurs when you try to connect from a host other than the one on which the MySQL server is running, it means that there is no row in the 'user' table with a 'Host' value that matches the client host:
Host ... is not allowed to connect to this MySQL server
You can fix this by setting up an account for the combination of client host name and user name that you are using when trying to connect.
If you do not know the IP address or host name of the machine from which you are connecting, you should put a row with ''%'' as the 'Host' column value in the 'user' table. After trying to connect from the client machine, use a 'SELECT USER()' query to see how you really did connect. Then change the ''%'' in the 'user' table row to the actual host name that shows up in the log. Otherwise, your system is left insecure because it permits connections from any host for the given user name.
On Linux, another reason that this error might occur is that you are using a binary MySQL version that is compiled with a different version of the 'glibc' library than the one you are using. In this case, you should either upgrade your operating system or 'glibc', or download a source distribution of MySQL version and compile it yourself. A source RPM is normally trivial to compile and install, so this is not a big problem.
If you specify a host name when trying to connect, but get an error message where the host name is not shown or is an IP address, it means that the MySQL server got an error when trying to resolve the IP address of the client host to a name:
$> mysqladmin -u root -pXXXX -h SOME_HOSTNAME ver
Access denied for user 'root'@'' (using password: YES)
If you try to connect as 'root' and get the following error, it means that you do not have a row in the 'user' table with a 'User' column value of ''root'' and that *note 'mysqld': mysqld. cannot resolve the host name for your client:
Access denied for user ''@'unknown'
These errors indicate a DNS problem. To fix it, execute note 'mysqladmin flush-hosts': mysqladmin. to reset the internal DNS host cache. See note host-cache::.
Some permanent solutions are:
* Determine what is wrong with your DNS server and fix it.
* Specify IP addresses rather than host names in the MySQL grant
tables.
* Put an entry for the client machine name in '/etc/hosts' on
Unix or '\windows\hosts' on Windows.
* Start *note 'mysqld': mysqld. with the 'skip_name_resolve'
system variable enabled.
* Start *note 'mysqld': mysqld. with the '--skip-host-cache'
option.
* On Unix, if you are running the server and the client on the
same machine, connect to 'localhost'. For connections to
'localhost', MySQL programs attempt to connect to the local
server by using a Unix socket file, unless there are
connection parameters specified to ensure that the client
makes a TCP/IP connection. For more information, see *note
connecting::.
* On Windows, if you are running the server and the client on
the same machine and the server supports named pipe
connections, connect to the host name '.' (period).
Connections to '.' use a named pipe rather than TCP/IP.
If 'mysql -u root' works but 'mysql -h YOUR_HOSTNAME -u root' results in 'Access denied' (where YOUR_HOSTNAME is the actual host name of the local host), you may not have the correct name for your host in the 'user' table. A common problem here is that the 'Host' value in the 'user' table row specifies an unqualified host name, but your system's name resolution routines return a fully qualified domain name (or vice versa). For example, if you have a row with host ''pluto'' in the 'user' table, but your DNS tells MySQL that your host name is ''pluto.example.com'', the row does not work. Try adding a row to the 'user' table that contains the IP address of your host as the 'Host' column value. (Alternatively, you could add a row to the 'user' table with a 'Host' value that contains a wildcard (for example, ''pluto.%''). However, use of 'Host' values ending with '%' is insecure and is not recommended!)
If 'mysql -u USER_NAME' works but 'mysql -u USER_NAME SOME_DB' does not, you have not granted access to the given user for the database named SOME_DB.
If 'mysql -u USER_NAME' works when executed on the server host, but 'mysql -h HOST_NAME -u USER_NAME' does not work when executed on a remote client host, you have not enabled access to the server for the given user name from the remote host.
If you cannot figure out why you get 'Access denied', remove from the 'user' table all rows that have 'Host' values containing wildcards (rows that contain ''%'' or ''_'' characters). A very common error is to insert a new row with 'Host'=''%'' and 'User'=''SOME_USER'', thinking that this enables you to specify 'localhost' to connect from the same machine. The reason that this does not work is that the default privileges include a row with 'Host'=''localhost'' and 'User'=''''. Because that row has a 'Host' value ''localhost'' that is more specific than ''%'', it is used in preference to the new row when connecting from 'localhost'! The correct procedure is to insert a second row with 'Host'=''localhost'' and 'User'=''SOME_USER'', or to delete the row with 'Host'=''localhost'' and 'User'=''''. After deleting the row, remember to issue a 'FLUSH PRIVILEGES' statement to reload the grant tables. See also *note connection-access::.
If you are able to connect to the MySQL server, but get an 'Access denied' message whenever you issue a note 'SELECT ... INTO OUTFILE': select-into. or note 'LOAD DATA': load-data. statement, your row in the 'user' table does not have the 'FILE' privilege enabled.
If you change the grant tables directly (for example, by using note 'INSERT': insert, note 'UPDATE': update, or note 'DELETE': delete. statements) and your changes seem to be ignored, remember that you must execute a 'FLUSH PRIVILEGES' statement or a note 'mysqladmin flush-privileges': mysqladmin. command to cause the server to reload the privilege tables. Otherwise, your changes have no effect until the next time the server is restarted. Remember that after you change the 'root' password with an *note 'UPDATE': update. statement, you do not need to specify the new password until after you flush the privileges, because the server does not yet know that you have changed the password.
If your privileges seem to have changed in the middle of a session, it may be that a MySQL administrator has changed them. Reloading the grant tables affects new client connections, but it also affects existing connections as indicated in *note privilege-changes::.
If you have access problems with a Perl, PHP, Python, or ODBC program, try to connect to the server with 'mysql -u USER_NAME DB_NAME' or 'mysql -u USER_NAME -pPASSWORD DB_NAME'. If you are able to connect using the *note 'mysql': mysql. client, the problem lies with your program, not with the access privileges. (There is no space between '-p' and the password; you can also use the '--password=PASSWORD' syntax to specify the password. If you use the '-p' or '--password' option with no password value, MySQL prompts you for the password.)
For testing purposes, start the note 'mysqld': mysqld. server with the '--skip-grant-tables' option. Then you can change the MySQL grant tables and use the note 'SHOW GRANTS': show-grants. statement to check whether your modifications have the desired effect. When you are satisfied with your changes, execute note 'mysqladmin flush-privileges': mysqladmin. to tell the note 'mysqld': mysqld. server to reload the privileges. This enables you to begin using the new grant table contents without stopping and restarting the server.
If everything else fails, start the note 'mysqld': mysqld. server with a debugging option (for example, '--debug=d,general,query'). This prints host and user information about attempted connections, as well as information about each command issued. See note dbug-package::.
If you have any other problems with the MySQL grant tables and ask on the MySQL Community Slack (https://mysqlcommunity.slack.com/), always provide a dump of the MySQL grant tables. You can dump the tables with the note 'mysqldump mysql': mysqldump. command. To file a bug report, see the instructions at note bug-reports::. In some cases, you may need to restart note 'mysqld': mysqld. with '--skip-grant-tables' to run note 'mysqldump': mysqldump.
File: manual.info.tmp, Node: account-activity-auditing, Prev: problems-connecting, Up: access-control
Applications can use the following guidelines to perform SQL-based auditing that ties database activity to MySQL accounts.
MySQL accounts correspond to rows in the 'mysql.user' system table. When a client connects successfully, the server authenticates the client to a particular row in this table. The 'User' and 'Host' column values in this row uniquely identify the account and correspond to the ''USER_NAME'@'HOST_NAME'' format in which account names are written in SQL statements.
The account used to authenticate a client determines which privileges the client has. Normally, the 'CURRENT_USER()' function can be invoked to determine which account this is for the client user. Its value is constructed from the 'User' and 'Host' columns of the 'user' table row for the account.
However, there are circumstances under which the 'CURRENT_USER()' value corresponds not to the client user but to a different account. This occurs in contexts when privilege checking is not based the client's account:
Stored routines (procedures and functions) defined with the 'SQL SECURITY DEFINER' characteristic
Views defined with the 'SQL SECURITY DEFINER' characteristic
Triggers and events
In those contexts, privilege checking is done against the 'DEFINER' account and 'CURRENT_USER()' refers to that account, not to the account for the client who invoked the stored routine or view or who caused the trigger to activate. To determine the invoking user, you can call the 'USER()' function, which returns a value indicating the actual user name provided by the client and the host from which the client connected. However, this value does not necessarily correspond directly to an account in the 'user' table, because the 'USER()' value never contains wildcards, whereas account values (as returned by 'CURRENT_USER()') may contain user name and host name wildcards.
For example, a blank user name matches any user, so an account of '''@'localhost'' enables clients to connect as an anonymous user from the local host with any user name. In this case, if a client connects as 'user1' from the local host, 'USER()' and 'CURRENT_USER()' return different values:
mysql> SELECT USER(), CURRENT_USER();
+-----------------+----------------+
| USER() | CURRENT_USER() |
+-----------------+----------------+
| user1@localhost | @localhost |
+-----------------+----------------+
The host name part of an account can contain wildcards, too. If the host name contains a ''%'' or ''_'' pattern character or uses netmask notation, the account can be used for clients connecting from multiple hosts and the 'CURRENT_USER()' value does not indicate which one. For example, the account ''user2'@'%.example.com'' can be used by 'user2' to connect from any host in the 'example.com' domain. If 'user2' connects from 'remote.example.com', 'USER()' and 'CURRENT_USER()' return different values:
mysql> SELECT USER(), CURRENT_USER();
+--------------------------+---------------------+
| USER() | CURRENT_USER() |
+--------------------------+---------------------+
| user2@remote.example.com | user2@%.example.com |
+--------------------------+---------------------+
If an application must invoke 'USER()' for user auditing (for example, if it does auditing from within triggers) but must also be able to associate the 'USER()' value with an account in the 'user' table, it is necessary to avoid accounts that contain wildcards in the 'User' or 'Host' column. Specifically, do not permit 'User' to be empty (which creates an anonymous-user account), and do not permit pattern characters or netmask notation in 'Host' values. All accounts must have a nonempty 'User' value and literal 'Host' value.
With respect to the previous examples, the '''@'localhost'' and ''user2'@'%.example.com'' accounts should be changed not to use wildcards:
RENAME USER ''@'localhost' TO 'user1'@'localhost';
RENAME USER 'user2'@'%.example.com' TO 'user2'@'remote.example.com';
If 'user2' must be able to connect from several hosts in the 'example.com' domain, there should be a separate account for each host.
To extract the user name or host name part from a 'CURRENT_USER()' or 'USER()' value, use the 'SUBSTRING_INDEX()' function:
mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',1);
+---------------------------------------+
| SUBSTRING_INDEX(CURRENT_USER(),'@',1) |
+---------------------------------------+
| user1 |
+---------------------------------------+
mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);
+----------------------------------------+
| SUBSTRING_INDEX(CURRENT_USER(),'@',-1) |
+----------------------------------------+
| localhost |
+----------------------------------------+
File: manual.info.tmp, Node: encrypted-connections, Next: security-plugins, Prev: access-control, Up: security