How the Privilege System Works

The MySQL privilege system ensures that all users may perform exactly the operations that they are supposed to be allowed to do. When you connect to a MySQL server, your identity is determined by the host from which you connect and the username you specify. The system grants privileges according to your identity and what you want to do.

MySQL considers both your hostname and username in identifying you because there is little reason to assume that a given username belongs to the same person everywhere on the Internet. For example, the user joe who connects from office.com need not be the same person as the user joe who connects from elsewhere.com. MySQL handles this by allowing you to distinguish users on different hosts that happen to have the same name: you can grant joe one set of privileges for connections from office.com, and a different set of privileges for connections from elsewhere.com.

MySQL access control involves two stages:

Note that if your privileges are changed (either by yourself or someone else) while you are connected, those changes will not necessarily take effect with your next query or queries. See Privilege changes for details.

The server uses the user, db, and host tables in the mysql database at both stages of access control. The fields in these grant tables are shown here:

Table nameuserdbhost
Scope fieldsHostHostHost
 UserDbDb
 PasswordUser 
Privilege fieldsSelect_privSelect_privSelect_priv
 Insert_privInsert_privInsert_priv
 Update_privUpdate_privUpdate_priv
 Delete_privDelete_privDelete_priv
 Index_privIndex_privIndex_priv
 Alter_privAlter_privAlter_priv
 Create_privCreate_privCreate_priv
 Drop_privDrop_privDrop_priv
 Grant_privGrant_privGrant_priv
 References_privReferences_privReferences_priv
 Reload_priv  
 Shutdown_priv  
 Process_priv  
 File_priv  
 Show_db_priv  
 Super_priv  
 Create_tmp_table_privCreate_tmp_table_privCreate_tmp_table_priv
 Lock_tables_privLock_tables_privLock_tables_priv
 Execute_priv  
 Repl_slave_priv  
 Repl_client_priv  
 ssl_type  
 ssl_cypher  
 x509_issuer  
 x509_cubject  
 max_questions  
 max_updates  
 max_connections  

For the second stage of access control (request verification), the server may, if the request involves tables, additionally consult the tables_priv and columns_priv tables. The fields in these tables are shown here:

Table nametables_privcolumns_priv
Scope fieldsHostHost
 DbDb
 UserUser
 Table_nameTable_name
  Column_name
Privilege fieldsTable_privColumn_priv
 Column_priv 
Other fieldsTimestampTimestamp
 Grantor 

Each grant table contains scope fields and privilege fields.

Scope fields determine the scope of each entry in the tables, that is, the context in which the entry applies. For example, a user table entry with Host and User values of 'thomas.loc.gov' and 'bob' would be used for authenticating connections made to the server by bob from the host thomas.loc.gov. Similarly, a db table entry with Host, User, and Db fields of 'thomas.loc.gov', 'bob' and 'reports' would be used when bob connects from the host thomas.loc.gov to access the reports database. The tables_priv and columns_priv tables contain scope fields indicating tables or table/column combinations to which each entry applies.

For access-checking purposes, comparisons of Host values are case-insensitive. User, Password, Db, and Table_name values are case-sensitive. Column_name values are case-insensitive in MySQL Version 3.22.12 or later.

Privilege fields indicate the privileges granted by a table entry, that is, what operations can be performed. The server combines the information in the various grant tables to form a complete description of a user's privileges. The rules used to do this are described in Request access.

Scope fields are strings, declared as shown here; the default value for each is the empty string:

Field nameTypeNotes
HostCHAR(60) 
UserCHAR(16) 
PasswordCHAR(16) 
DbCHAR(64)(CHAR(60) for the tables_priv and columns_priv tables)
Table_nameCHAR(60) 
Column_nameCHAR(60) 

In the user, db and host tables, all privilege fields are declared as ENUM('N','Y')---each can have a value of 'N' or 'Y', and the default value is 'N'.

In the tables_priv and columns_priv tables, the privilege fields are declared as SET fields:

Table nameField namePossible set elements
tables_privTable_priv'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
tables_privColumn_priv'Select', 'Insert', 'Update', 'References'
columns_privColumn_priv'Select', 'Insert', 'Update', 'References'

Briefly, the server uses the grant tables like this:

Note that administrative privileges (RELOAD, SHUTDOWN, etc.) are specified only in the user table. This is because administrative operations are operations on the server itself and are not database-specific, so there is no reason to list such privileges in the other grant tables. In fact, only the user table need be consulted to determine whether you can perform an administrative operation.

The FILE privilege is specified only in the user table, too. It is not an administrative privilege as such, but your ability to read or write files on the server host is independent of the database you are accessing.

The mysqld server reads the contents of the grant tables once, when it starts up. Changes to the grant tables take effect as indicated in Privilege changes.

When you modify the contents of the grant tables, it is a good idea to make sure that your changes set up privileges the way you want. For help in diagnosing problems, see Access denied. For advice on security issues, see Security.

A useful diagnostic tool is the mysqlaccess script, which Yves Carlier has provided for the MySQL distribution. Invoke mysqlaccess with the --help option to find out how it works. Note that mysqlaccess checks access using only the user, db and host tables. It does not check table- or column-level privileges.