The world's most popular open source database
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type]
{
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
}
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user [IDENTIFIED BY [PASSWORD] 'password']] ...
[REQUIRE
NONE |
[{SSL| X509}]
[CIPHER 'cipher' [AND]]
[ISSUER 'issuer' [AND]]
[SUBJECT 'subject']]
[WITH with_option [with_option] ...]
object_type =
TABLE
| FUNCTION
| PROCEDURE
with_option =
GRANT OPTION
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
The GRANT statement enables
system administrators to create MySQL user accounts and to grant
rights to accounts. To use GRANT,
you must have the GRANT OPTION
privilege, and you must have the privileges that you are
granting. The REVOKE statement is
related and enables administrators to remove account privileges.
See Section 12.5.1.5, “REVOKE Syntax”.
MySQL Enterprise. For automated notification of users with inappropriate privileges, subscribe to the MySQL Enterprise Monitor. For more information, see http://www.mysql.com/products/enterprise/advisors.html.
MySQL account information is stored in the tables of the
mysql database. This database and the access
control system are discussed extensively in
Chapter 5, MySQL Server Administration, which you should
consult for additional details.
Some releases of MySQL introduce changes to the structure of the grant tables to add new privileges or features. Whenever you update to a new version of MySQL, you should update your grant tables to make sure that they have the current structure so that you can take advantage of any new capabilities. See Section 4.4.8, “mysql_upgrade — Check Tables for MySQL Upgrade”.
If the grant tables hold privilege rows that contain mixed-case
database or table names and the
lower_case_table_names system
variable is set to a non-zero value,
REVOKE cannot be used to revoke
these privileges. It will be necessary to manipulate the grant
tables directly. (GRANT will not
create such rows when
lower_case_table_names is set,
but such rows might have been created prior to setting the
variable.)
Privileges can be granted at several levels. The examples shown
here include no IDENTIFIED BY
' clause for
brevity, but you should include one if the account does not
already exist to avoid creating an account with no password.
password'
Global level
Global privileges apply to all databases on a given server.
These privileges are stored in the
mysql.user table. GRANT ALL ON
*.* and REVOKE ALL ON *.* grant
and revoke only global privileges.
GRANT ALL ON *.* TO 'someuser'@'somehost'; GRANT SELECT, INSERT ON *.* TO 'someuser'@'somehost';
Database level
Database privileges apply to all objects in a given
database. These privileges are stored in the
mysql.db and
mysql.host tables. GRANT ALL ON
and
db_name.*REVOKE ALL ON
grant and
revoke only database privileges.
db_name.*
GRANT ALL ON mydb.* TO 'someuser'@'somehost'; GRANT SELECT, INSERT ON mydb.* TO 'someuser'@'somehost';
Table level
Table privileges apply to all columns in a given table.
These privileges are stored in the
mysql.tables_priv table. GRANT
ALL ON
and db_name.tbl_nameREVOKE ALL ON
grant
and revoke only table privileges.
db_name.tbl_name
GRANT ALL ON mydb.mytbl TO 'someuser'@'somehost'; GRANT SELECT, INSERT ON mydb.mytbl TO 'someuser'@'somehost';
If you specify tbl_name rather
than db_name.tbl_name, the statement
applies to tbl_name in the
default database.
Column level
Column privileges apply to single columns in a given table.
These privileges are stored in the
mysql.columns_priv table. When using
REVOKE, you must specify the
same columns that were granted. The column or columns for
which the privileges are to be granted must be enclosed
within parentheses.
GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'@'somehost';
Routine level
The CREATE ROUTINE,
ALTER ROUTINE,
EXECUTE, and
GRANT OPTION privileges apply
to stored routines (functions and procedures). They can be
granted at the global and database levels. Also, except for
CREATE ROUTINE, these
privileges can be granted at the routine level for
individual routines and are stored in the
mysql.procs_priv table.
GRANT CREATE ROUTINE ON mydb.* TO 'someuser'@'somehost'; GRANT EXECUTE ON PROCEDURE mydb.myproc TO 'someuser'@'somehost';
The object_type clause should be
specified as TABLE,
FUNCTION, or PROCEDURE
when the following object is a table, a stored function, or a
stored procedure.
If you specify ON * and you have
not selected a default database, the
privileges granted are global.
For the GRANT and
REVOKE statements,
priv_type can be specified as any of
the following:
| Privilege | Meaning |
ALL [PRIVILEGES] |
Grants all privileges at specified access level except
GRANT OPTION
|
ALTER |
Enables use of ALTER TABLE
|
ALTER ROUTINE |
Enables stored routines to be altered or dropped |
CREATE |
Enables use of CREATE TABLE
|
CREATE ROUTINE |
Enables creation of stored routines |
CREATE TEMPORARY TABLES |
Enables use of CREATE TEMPORARY TABLE
|
CREATE USER |
Enables use of CREATE USER,
DROP USER,
RENAME USER, and
REVOKE ALL PRIVILEGES. |
CREATE VIEW |
Enables use of CREATE VIEW
|
DELETE |
Enables use of DELETE
|
DROP |
Enables use of DROP TABLE
|
EVENT |
Enables creation of events for the event scheduler |
EXECUTE |
Enables the user to run stored routines |
FILE |
Enables use of SELECT ... INTO OUTFILE and
LOAD DATA
INFILE
|
INDEX |
Enables use of CREATE INDEX and
DROP INDEX
|
INSERT |
Enables use of INSERT
|
LOCK TABLES |
Enables use of LOCK TABLES on tables for
which you have the SELECT
privilege |
PROCESS |
Enables the user to see all processes with SHOW
PROCESSLIST
|
REFERENCES |
Not implemented |
RELOAD |
Enables use of FLUSH
|
REPLICATION CLIENT |
Enables the user to ask where slave or master servers are |
REPLICATION SLAVE |
Needed for replication slaves (to read binary log events from the master) |
SELECT |
Enables use of SELECT
|
SHOW DATABASES |
SHOW DATABASES shows all databases |
SHOW VIEW |
Enables use of SHOW CREATE VIEW
|
SHUTDOWN |
Enables use of mysqladmin shutdown |
SUPER |
Enables use of CHANGE MASTER TO,
KILL,
PURGE BINARY LOGS, and
SET
GLOBAL statements, the mysqladmin
debug command; allows you to connect (once)
even if max_connections
is reached |
TRIGGER |
Enables the user to create or drop triggers |
UPDATE |
Enables use of UPDATE
|
USAGE |
Synonym for “no privileges” |
GRANT OPTION |
Enables privileges to be granted |
The EVENT and
TRIGGER privileges were added in
MySQL 5.1.6. A trigger is associated with a table, so to create
or drop a trigger, you must have the
TRIGGER privilege for the table,
not the trigger. (Before MySQL 5.1.6, the
SUPER privilege was required to
create or drop triggers.)
The REFERENCES privilege
currently is unused.
USAGE can be specified when you
want to create a user that has no privileges.
Use SHOW GRANTS to determine what
privileges an account has. See Section 12.5.5.22, “SHOW GRANTS Syntax”.
You can assign global privileges by using ON
*.* syntax or database-level privileges by using
ON
syntax. If you specify db_name.*ON * and you have
selected a default database, the privileges are granted in that
database.
The FILE,
PROCESS,
RELOAD,
REPLICATION CLIENT,
REPLICATION SLAVE,
SHOW DATABASES,
SHUTDOWN,
SUPER, and
CREATE USER privileges are
administrative privileges that can only be granted globally
(using ON *.* syntax).
Other privileges can be granted globally or at more specific levels.
The priv_type values that you can
specify for a table are SELECT,
INSERT,
UPDATE,
DELETE,
CREATE,
DROP, GRANT
OPTION, INDEX,
ALTER,
CREATE VIEW,
SHOW VIEW and
TRIGGER.
The priv_type values that you can
specify for a column (that is, when you use a
column_list clause) are
SELECT,
INSERT, and
UPDATE.
The priv_type values that you can
specify at the routine level are ALTER
ROUTINE, EXECUTE, and
GRANT OPTION.
CREATE ROUTINE is not a
routine-level privilege because you must have this privilege to
create a routine in the first place.
For the global, database, table, and routine levels,
GRANT ALL assigns only the privileges that
exist at the level you are granting. For example, GRANT
ALL ON is a
database-level statement, so it does not grant any global-only
privileges such as db_name.*FILE.
MySQL allows you to grant privileges even on database objects
that do not exist. In such cases, the privileges to be granted
must include the CREATE
privilege. This behavior is by design, and
is intended to enable the database administrator to prepare user
accounts and privileges for database objects that are to be
created at a later time.
MySQL does not automatically revoke any privileges when you drop a table or database. However, if you drop a routine, any routine-level privileges granted for that routine are revoked.
The “_” and
“%” wildcards are allowed when
specifying database names in
GRANT statements that grant
privileges at the global or database levels. This means, for
example, that if you want to use a
“_” character as part of a
database name, you should specify it as
“\_” in the
GRANT statement, to prevent the
user from being able to access additional databases matching
the wildcard pattern; for example, GRANT ... ON
`foo\_bar`.* TO ....
To accommodate granting rights to users from arbitrary hosts,
MySQL supports specifying the user
value in the form
.
If a user_name@host_nameuser_name or
host_name value is legal as an
unquoted identifier, you need not quote it. However, quotes are
necessary to specify a user_name
string containing special characters (such as
“-”), or a
host_name string containing special
characters or wildcard characters (such as
“%”); for example,
'test-user'@'test-hostname'. Quote the
username and hostname separately.
You can specify wildcards in the hostname. For example,
applies to user_name@'%.loc.gov'user_name for any host in
the loc.gov domain, and
applies to user_name@'144.155.166.%'user_name for any host in
the 144.155.166 class C subnet.
The simple form user_name is a
synonym for
.
user_name@'%'
MySQL does not support wildcards in
usernames. Anonymous users are defined by inserting
entries with User='' into the
mysql.user table or by creating a user with
an empty name with the GRANT
statement:
GRANT ALL ON test.* TO ''@'localhost' ...
When specifying quoted values, quote database, table, column,
and routine names as identifiers, using backticks
(“`”). Quote hostnames and
usernames as identifiers or as strings, using either backticks
or single quotes (“'”). Quote
passwords as strings, using single quotes.
If you allow anonymous users to connect to the MySQL server,
you should also grant privileges to all local users as
.
Otherwise, the anonymous user account for
user_name@localhostlocalhost in the
mysql.user table (created during MySQL
installation) is used when named users try to log in to the
MySQL server from the local machine. For details, see
Section 5.4.4, “Access Control, Stage 1: Connection Verification”.
You can determine whether this applies to you by executing the following query, which lists any anonymous users:
SELECT Host, User FROM mysql.user WHERE User='';
If you want to delete the local anonymous user account to avoid the problem just described, use these statements:
DELETE FROM mysql.user WHERE Host='localhost' AND User=''; FLUSH PRIVILEGES;
GRANT supports hostnames up to 60
characters long. Database, table, column, and routine names can
be up to 64 characters. Usernames can be up to 16 characters.
The allowable length for usernames cannot be changed
by altering the mysql.user table, and
attempting to do so results in unpredictable behavior which
may even make it impossible for users to log in to the MySQL
server. You should never alter any of the tables in
the mysql database in any manner whatsoever
except by means of the procedure prescribed by MySQL AB that
is described in Section 4.4.8, “mysql_upgrade — Check Tables for MySQL Upgrade”.
The privileges for a table, column, or routine are formed
additively as the logical OR of the
privileges at each of the privilege levels. For example, if the
mysql.user table specifies that a user has a
global SELECT privilege, the
privilege cannot be denied by an entry at the database, table,
or column level.
The privileges for a column can be calculated as follows:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges OR routine privileges
In most cases, you grant rights to a user at only one of the privilege levels, so life is not normally this complicated. The details of the privilege-checking procedure are presented in Section 5.4, “The MySQL Access Privilege System”.
If you grant privileges for a username/hostname combination that
does not exist in the mysql.user table, an
entry is added and remains there until deleted with a
DELETE statement. In other words,
GRANT may create
user table entries, but
REVOKE does not remove them; you
must do that explicitly using DROP
USER or DELETE.
If the account does not already exist,
GRANT creates it. In the case
that you create a new account or if you have global grant
privileges, the account's password is set to the password
specified by the IDENTIFIED BY clause, if one
is given. If the account already had a password, it is replaced
by the new one.
If you create a new user but do not specify an
IDENTIFIED BY clause, the user has no
password. This is very insecure. However, you can enable the
NO_AUTO_CREATE_USER SQL mode
to prevent GRANT from creating
a new user if it would otherwise do so, unless
IDENTIFIED BY is given to provide the new
user a non-empty password.
MySQL Enterprise. The MySQL Enterprise Monitor specifically guards against user accounts with no passwords. To find out more, see http://www.mysql.com/products/enterprise/advisors.html.
Passwords can also be set with the SET
PASSWORD statement. See
Section 12.5.1.6, “SET PASSWORD Syntax”.
In the IDENTIFIED BY clause, the password
should be given as the literal password value. It is unnecessary
to use the PASSWORD() function as
it is for the SET PASSWORD
statement. For example:
GRANT ... IDENTIFIED BY 'mypass';
If you do not want to send the password in clear text and you
know the hashed value that
PASSWORD() would return for the
password, you can specify the hashed value preceded by the
keyword PASSWORD:
GRANT ... IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
In a C program, you can get the hashed value by using the
make_scrambled_password() C API function.
If you grant privileges for a database, an entry in the
mysql.db table is created if needed. If all
privileges for the database are removed with
REVOKE, this entry is deleted.
The SHOW DATABASES privilege
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.
MySQL Enterprise.
The SHOW DATABASES privilege
should be granted only to users who need to see all the
databases on a MySQL server. Subscribers to the MySQL
Enterprise Monitor are alerted when servers are started
without the --skip-show-database option. For
more information, see
http://www.mysql.com/products/enterprise/advisors.html.
If a user has no privileges for a table, the table name is not
displayed when the user requests a list of tables (for example,
with a SHOW TABLES statement).
The WITH GRANT OPTION clause gives the user
the ability to give to other users any privileges the user has
at the specified privilege level. You should be careful to whom
you give the GRANT OPTION
privilege, because two users with different privileges may be
able to join privileges!
You cannot grant another user a privilege which you yourself do
not have; the GRANT OPTION
privilege enables you to assign only those privileges which you
yourself possess.
Be aware that when you grant a user the
GRANT OPTION privilege at a
particular privilege level, any privileges the user possesses
(or may be given in the future) at that level can also be
granted by that user to other users. Suppose that you grant a
user the INSERT privilege on a
database. If you then grant the
SELECT privilege on the database
and specify WITH GRANT OPTION, that user can
give to other users not only the
SELECT privilege, but also
INSERT. If you then grant the
UPDATE privilege to the user on
the database, the user can grant
INSERT,
SELECT, and
UPDATE.
For a non-administrative user, you should not grant the
ALTER privilege globally or for
the mysql database. If you do that, the user
can try to subvert the privilege system by renaming tables!
The MAX_QUERIES_PER_HOUR
,
countMAX_UPDATES_PER_HOUR
, and
countMAX_CONNECTIONS_PER_HOUR
options limit the
number of queries, updates, and logins a user can perform during
any given one-hour period. (Queries for which results are served
from the query cache do not count against the
countMAX_QUERIES_PER_HOUR limit.) If
count is 0 (the
default), this means that there is no limitation for that user.
The MAX_USER_CONNECTIONS
option limits the
maximum number of simultaneous connections that the account can
make. If countcount is
0 (the default), the
max_user_connections system
variable determines the number of simultaneous connections for
the account.
Note: To specify any of these resource-limit options for an
existing user without affecting existing privileges, use
GRANT USAGE ON *.* ... WITH MAX_....
See Section 5.5.4, “Limiting Account Resources”.
MySQL can check X509 certificate attributes in addition to the
usual authentication that is based on the username and password.
To specify SSL-related options for a MySQL account, use the
REQUIRE clause of the
GRANT statement. (For background
information on the use of SSL with MySQL, see
Section 5.5.7, “Using SSL for Secure Connections”.)
There are a number of different possibilities for limiting connection types for a given account:
REQUIRE NONE indicates that the account
has no SSL or X509 requirements. This is the default if no
SSL-related REQUIRE options are
specified. Unencrypted connections are allowed if the
username and password are valid. However, encrypted
connections can also be used, at the client's option, if the
client has the proper certificate and key files. That is,
the client need not specify any SSL command options, in
which case the connection will be unencrypted. To use an
encrypted connection, the client must specify either the
--ssl-ca option, or all three of the
--ssl-ca, --ssl-key, and
--ssl-cert options.
The REQUIRE SSL option tells the server
to allow only SSL-encrypted connections for the account.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE SSL;
To connect, the client must specify the
--ssl-ca option, and may additionally
specify the --ssl-key and
--ssl-cert options.
REQUIRE X509 means that the client must
have a valid certificate but that the exact certificate,
issuer, and subject do not matter. The only requirement is
that it should be possible to verify its signature with one
of the CA certificates.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE X509;
To connect, the client must specify the
--ssl-ca, --ssl-key, and
--ssl-cert options. This is also true for
ISSUER and SUBJECT
because those REQUIRE options imply
X509.
REQUIRE ISSUER
' places the
restriction on connection attempts that the client must
present a valid X509 certificate issued by CA
issuer''. If
the client presents a certificate that is valid but has a
different issuer, the server rejects the connection. Use of
X509 certificates always implies encryption, so the
issuer'SSL option is unnecessary in this case.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
IDENTIFIED BY 'goodsecret'
REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';
Note that the
' value
should be entered as a single string.
issuer'
REQUIRE SUBJECT
' places the
restriction on connection attempts that the client must
present a valid X509 certificate containing the subject
subject'subject. If the client presents a
certificate that is valid but has a different subject, the
server rejects the connection.
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
IDENTIFIED BY 'goodsecret'
REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
O=MySQL demo client certificate/
CN=Tonu Samuel/Email=tonu@example.com';
Note that the
'
value should be entered as a single string.
subject'
REQUIRE CIPHER
' is needed to
ensure that ciphers and key lengths of sufficient strength
are used. SSL itself can be weak if old algorithms using
short encryption keys are used. Using this option, you can
ask that a specific cipher method is used to allow a
connection.
cipher'
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' IDENTIFIED BY 'goodsecret' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';
The SUBJECT, ISSUER, and
CIPHER options can be combined in the
REQUIRE clause like this:
GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
IDENTIFIED BY 'goodsecret'
REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
O=MySQL demo client certificate/
CN=Tonu Samuel/Email=tonu@example.com'
AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
The AND keyword is optional between
REQUIRE options.
The order of the options does not matter, but no option can be specified twice.
When mysqld starts, all privileges are read into memory. For details, see Section 5.4.6, “When Privilege Changes Take Effect”.
Note that if you are using table, column, or routine privileges for even one user, the server examines table, column, and routine privileges for all users and this slows down MySQL a bit. Similarly, if you limit the number of queries, updates, or connections for any users, the server must monitor these values.
The biggest differences between the standard SQL and MySQL
versions of GRANT are:
In MySQL, privileges are associated with the combination of a hostname and username and not with only a username.
Standard SQL does not have global or database-level privileges, nor does it support all the privilege types that MySQL supports.
MySQL does not support the standard SQL
UNDER privilege.
Standard SQL privileges are structured in a hierarchical
manner. If you remove a user, all privileges the user has
been granted are revoked. This is also true in MySQL if you
use DROP USER. See
Section 12.5.1.2, “DROP USER Syntax”.
In standard SQL, when you drop a table, all privileges for
the table are revoked. In standard SQL, when you revoke a
privilege, all privileges that were granted based on that
privilege are also revoked. In MySQL, privileges can be
dropped only with explicit
REVOKE statements or by
manipulating values stored in the MySQL grant tables.
In MySQL, it is possible to have the
INSERT privilege for only
some of the columns in a table. In this case, you can still
execute INSERT statements on
the table, provided that you omit those columns for which
you do not have the INSERT
privilege. The omitted columns are set to their implicit
default values if strict SQL mode is not enabled. In strict
mode, the statement is rejected if any of the omitted
columns have no default value. (Standard SQL requires you to
have the INSERT privilege on
all columns.) Section 5.1.7, “Server SQL Modes”, discusses
strict mode. Section 10.1.4, “Data Type Default Values”, discusses
implicit default values.


User Comments
The normal response from a grant or revoke
statement is "Query OK, 0 rows affected". The
message that zero rows were affected is a common
source of confusion, but should just be ignored by
the user. Trying to revoke grants that were never
granted yields an "ERROR 1147: There is no such
grant defined for user...".
It would be helpful to link the paragraph on the 'WITH GRANT OPTION' to the '--safe-user-create' start option for mysqld.
It may be obvious to experienced users that the GRANT option not only allows to give privileges to existing users, but also to create new users this way. However, it is not intuitive how to restrict this.
Privilege SELECT also allows to execute SHOW CREATE TABLE statement.
If you use FEDERATED storage engine, and password given in the connection string is stored as plain text, it can be seen by any user who only has SELECT privilege and use SHOW CREATE TABLE statement.
Dennis Yu on January 16 2007 9:37am points out
> Privilege SELECT also allows to execute SHOW CREATE TABLE statement.
Indeed, the table showing priv_type meanings, gives:
> SELECT Enables use of SELECT
However, a number of MySQL commands are, effectively, synonyms for SELECT.
DESCRIBE is also a synonym for SELECT, and there may be more such commands.
It was only when I starting digging around in depth with the MySQL implementation of X.509 based security that I realised that the "REQUIRE" clause information is held in the mysql.user table and not in the other privilege tables. The result is that once you issue a GRANT statement for a given user that includes a REQUIRE, this applies to all privileges the user has or will have.
Thinking about it, this is probably the correct behaviour, but could catch out the unwary.
Add your own comment.