13.7.1.4 GRANT 声明

GRANT
    priv_type [(column_list)]
      [, priv_type [(column_list)]] ...
    ON [object_type] priv_level
    TO user [auth_option] [, user [auth_option]] ...
    [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
    [WITH {GRANT OPTION | resource_option} ...]

GRANT PROXY ON user
    TO user [, user] ...
    [WITH GRANT OPTION]

object_type: {
    TABLE
  | FUNCTION
  | PROCEDURE
}

priv_level: {
    *
  | *.*
  | db_name.*
  | db_name.tbl_name
  | tbl_name
  | db_name.routine_name
}

user:
    (see Section6.2.4, "Specifying Account Names")

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

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

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

GRANT语句向 MySQL 用户帐户授予特权。 GRANT语句有多个方面,在以下主题下进行了介绍:

GRANT 概述

GRANT语句向 MySQL 用户帐户授予特权。

要使用GRANT授予特权,您必须具有GRANT OPTION特权,并且您必须具有要授予的特权。 (或者,如果您对mysql系统数据库中的授予 table 具有UPDATE特权,则可以向任何帐户授予任何特权。)启用read_only系统变量时,GRANT还需要SUPER特权。

REVOKE语句与GRANT相关,并使 Management 员可以删除帐户特权。参见第 13.7.1.6 节“ REVOKE 语句”

每个帐户名称都使用第 6.2.4 节“指定帐户名”中描述的格式。例如:

GRANT ALL ON db1.* TO 'jeffrey'@'localhost';

帐户的主机名部分(如果省略)默认为'%'

通常,数据库 Management 员首先使用CREATE USER创建一个帐户并定义其非特权 Feature,例如其密码,是否使用安全连接以及对服务器资源的访问限制,然后使用GRANT定义其特权。 ALTER USER可用于更改现有帐户的非特权 Feature。例如:

CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON db1.* TO 'jeffrey'@'localhost';
GRANT SELECT ON db2.invoice TO 'jeffrey'@'localhost';
ALTER USER 'jeffrey'@'localhost' WITH MAX_QUERIES_PER_HOUR 90;

Note

此处显示的示例不包含IDENTIFIED子句。假定您在创建帐户时使用CREATE USER设置密码,以避免创建不安全的帐户。

Note

如果在GRANT语句中命名的帐户尚不存在,则GRANT可以在稍后讨论NO_AUTO_CREATE_USER SQL 模式的条件下创建该帐户。也可以使用GRANT指定非特权帐户 Feature,例如是否使用安全连接以及对服务器资源的访问限制。

但是,自 MySQL 5.7.6 起,不建议使用GRANT来创建帐户或定义非特权 Feature。而是使用CREATE USERALTER USER执行这些任务。

mysql程序中,成功执行GRANT时以Query OK, 0 rows affected响应。要确定该操作会带来哪些特权,请使用SHOW GRANTS。参见第 13.7.5.21 节“ SHOW GRANTS 语句”

Important

在某些情况下,GRANT可能会记录在服务器日志中或 Client 端的历史记录文件(例如~/.mysql_history)中,这意味着任何具有对该信息的读取权限的人都可以读取明文密码。有关服务器日志发生这种情况的条件以及如何控制它的信息,请参阅第 6.1.2.3 节“密码和日志记录”。有关 Client 端日志记录的类似信息,请参见第 4.5.1.3 节“ mysqlClient 端记录”

GRANT支持最多 60 个字符的主机名。用户名最多可以包含 32 个字符。数据库,table,列和例程的名称最多可以包含 64 个字符。

Warning

请勿尝试通过更改mysql.user系统 table 来更改用户名的允许长度。这样做会导致无法预测的行为,甚至可能使用户无法登录到 MySQL 服务器。除通过第 2.11 节“升级 MySQL”中描述的过程外,切勿以任何方式更改mysql系统数据库中 table 的结构。

对象引用准则

GRANT语句中的多个对象均需加引号,尽管在许多情况下引号是可选的:帐户,数据库,table,列和例程名称。例如,如果帐户名中的* user_name host_name 值作为未加引号的标识符是合法的,则无需使用引号。但是,必须使用引号来指定包含特殊字符(例如-)的 user_name 字符串或包含特殊字符或例如%的通配符(例如'test-user'@'%.com')的 host_name *字符串。分别引用用户名和主机名。

要指定引用的值:

  • 引用数据库,table,列和例程名称作为标识符。

  • 用用户名和主机名加引号作为标识符或字符串。

  • 用密码引用字符串。

有关字符串引用和标识符引用的准则,请参见第 9.1.1 节“字符串 Literals”第 9.2 节“架构对象名称”

GRANT语句中指定数据库名称以在数据库级别(GRANT ... ON db_name.*)授予特权时,允许使用_%通配符。例如,这意味着要将_字符用作数据库名称的一部分,请在GRANT语句中将其指定为\_,以防止用户能够访问与通配符模式匹配的其他数据库(例如,) )。

如果不使用数据库名称在数据库级别授予特权,而是将其用作授予 table 或例程(例如GRANT ... ON db_name.tbl_name)之类的其他对象的特权的限定符,则通配符将被视为普通字符。

MySQL 支持的特权

下 table 总结了可以为GRANTREVOKE语句指定的* priv_type *特权类型,以及可以授予每个特权的级别。有关每种特权的更多信息,请参见第 6.2.2 节“ MySQL 提供的特权”

table13.8 授予和撤销的许可特权

Privilege含义和授予级别
ALL [PRIVILEGES]授予除GRANT OPTIONPROXY之外的指定访问级别的所有特权。
ALTER启用ALTER TABLE的使用。级别:全局,数据库,table。
ALTER ROUTINE使存储的例程能够被更改或删除。级别:全局,数据库,常规。
CREATE启用数据库和 table 创建。级别:全局,数据库,table。
CREATE ROUTINE启用存储的例程创建。级别:全局,数据库。
CREATE TABLESPACE启用 table 空间和日志文件组的创建,更改或删除。级别:Global。
创建临时 table启用创建临时 table的使用。级别:全局,数据库。
CREATE USER启用CREATE USERDROP USERRENAME USER撤销所有特权的使用。级别:Global。
CREATE VIEW启用视图的创建或更改。级别:全局,数据库,table。
DELETE启用DELETE的使用。级别:全局,数据库,table。
DROP启用要删除的数据库,table 和视图。级别:全局,数据库,table。
EVENT为事件计划程序启用事件的使用。级别:全局,数据库。
EXECUTE使用户能够执行存储的例程。级别:全局,数据库,常规。
FILE使用户能够使服务器读取或写入文件。级别:Global。
GRANT OPTION启用授予其他帐户特权或从其他帐户删除的特权。级别:全局,数据库,table,例程,代理。
INDEX启用要创建或删除的索引。级别:全局,数据库,table。
INSERT启用INSERT的使用。级别:全局,数据库,table,列。
LOCK TABLES在具有SELECT特权的 table 上启用LOCK TABLES的使用。级别:全局,数据库。
PROCESS使用户能够使用SHOW PROCESSLIST查看所有进程。级别:Global。
PROXY启用用户代理。级别:从一个用户到另一个用户。
REFERENCES启用外键创建。级别:全局,数据库,table,列。
RELOAD启用使用FLUSH操作。级别:Global。
REPLICATION CLIENT使用户能够询问源服务器或副本服务器在哪里。级别:Global。
REPLICATION SLAVE使副本能够从源读取二进制日志事件。级别:Global。
SELECT启用SELECT的使用。级别:全局,数据库,table,列。
SHOW DATABASES启用SHOW DATABASES以显示所有数据库。级别:Global。
SHOW VIEW启用显示创建视图的使用。级别:全局,数据库,table。
SHUTDOWN启用mysqladmin shutdown的使用。级别:Global。
SUPER启用其他 Management 操作的使用,例如更改为主KILL清除二进制日志SET GLOBALmysqladmin debug命令。级别:Global。
TRIGGER启用触发器操作。级别:全局,数据库,table。
UPDATE启用UPDATE的使用。级别:全局,数据库,table,列。
USAGE“没有特权”的同义词

触发器与 table 关联。要创建或删除触发器,您必须具有 table 的TRIGGER特权,而不是触发器。

GRANT语句中,必须自己命名ALL [PRIVILEGES]PROXY特权,并且不能与其他特权一起指定。 ALL [PRIVILEGES]代 table 授予特权级别的所有可用特权,但GRANT OPTIONPROXY特权除外。

可以指定USAGE来创建没有特权的用户,或者为帐户指定REQUIREWITH子句而不更改其现有特权。 (但是,不建议使用GRANT来定义非特权 Feature。

MySQL 帐户信息存储在mysql系统数据库的 table 中。有关其他详细信息,请查阅第 6.2 节“访问控制和帐户 Management”,该文章广泛讨论mysql系统数据库和访问控制系统。

如果授予 table 包含包含大小写混合的数据库或 table 名的特权行,并且lower_case_table_names系统变量设置为非零值,则不能使用REVOKE撤消这些特权。有必要直接操作授权 table。 (设置lower_case_table_namesGRANT不会创建此类行,但是此类行可能是在设置该变量之前创建的。)

可以在多个级别上授予特权,具体取决于ON子句使用的语法。对于REVOKE,相同的ON语法指定要删除的特权。

对于全局,数据库,table 和例行级别,GRANT ALL仅分配要授予的级别上存在的特权。例如,GRANT ALL ON db_name.*是数据库级别的语句,因此它不授予任何仅全局特权,例如FILE。授予ALL不会分配GRANT OPTIONPROXY特权。

如果以下对象是 table,存储函数或存储过程,则* object_type *子句(如果存在)应指定为TABLEFUNCTIONPROCEDURE

用户为数据库,table,列或例程持有的特权是作为每个特权级别(包括全局级别)的帐户特权的逻辑OR形成的。无法通过在较低级别上缺少该特权来拒绝在较高级别上授予的特权。例如,以下语句全局授予SELECTINSERT特权:

GRANT SELECT, INSERT ON *.* TO u1;

全局授予的特权适用于所有数据库,table 和列,即使未在任何较低级别上授予。

第 6.2.6 节“访问控制,第 2 阶段:请求验证”中提供了特权检查过程的详细信息。

如果您甚至为一个用户使用 table,列或例程特权,服务器将检查所有用户的 table,列和例程特权,这会使 MySQL 变慢。同样,如果您限制任何用户的查询,更新或连接数,则服务器必须监视这些值。

MySQL 使您可以授予不存在的数据库或 table 的特权。对于 table,要授予的特权必须包括CREATE特权。 此行为是设计使然,旨在使数据库 Management 员能够为稍后创建的数据库或 table 准备用户帐户和特权。

Important

当您删除数据库或 table 时,MySQL 不会自动取消任何特权。但是,如果删除例程,则为该例程授予的任何例程级特权都将被吊销。

帐户名和密码

GRANT语句中的* user 值 table 示该语句适用的 MySQL 帐户。为了适应从任意主机向用户授予权限,MySQL 支持以'user_name'@'host_name'形式指定 user *值。

您可以在主机名中指定通配符。例如,对于example.com域中的任何主机,'user_name'@'%.example.com'适用于* user_name ,对于198.51.100 C 类子网中的任何主机,'user_name'@'198.51.100.%'适用于 user_name *。

简单形式'user_name''user_name'@'%'的同义词。

  • MySQL 不支持用户名中的通配符*。要引用匿名用户,请使用GRANT语句指定一个用户名为空的帐户:
GRANT ALL ON test.* TO ''@'localhost' ...;

在这种情况下,将使用与匿名用户帐户相关联的特权,允许使用正确的匿名用户密码从 localhost 连接的任何用户访问。

有关帐户名中用户名和主机名值的其他信息,请参阅第 6.2.4 节“指定帐户名”

Warning

如果允许本地匿名用户连接到 MySQL 服务器,则还应将所有本地用户的特权授予'user_name'@'localhost'。否则,当命名用户尝试从本地计算机登录 MySQL 服务器时,将使用mysql.user系统 table 中localhost的匿名用户帐户。有关详细信息,请参见第 6.2.5 节“访问控制,第 1 阶段:连接验证”

要确定此问题是否适用于您,请执行以下查询,其中列出了所有匿名用户:

SELECT Host, User FROM mysql.user WHERE User='';

为避免上述问题,请使用以下语句删除本地匿名用户帐户:

DROP USER ''@'localhost';

对于允许* auth_option 值跟随 user 值的GRANT语法, auth_option *以IDENTIFIED开头,并通过指定帐户身份验证插件,凭据(例如密码)或两者来指示帐户的身份验证。 * auth_option *子句的语法与CREATE USER语句的语法相同。有关详细信息,请参见第 13.7.1.2 节“ CREATE USER 语句”

Note

从 MySQL 5.7.6 开始,不再使用GRANT定义帐户身份验证 Feature。而是使用CREATE USERALTER USER构建或更改身份验证 Feature。 GRANT功能将在将来的 MySQL 版本中删除。

如果存在IDENTIFIED并且您具有全局授予特权(GRANT OPTION),则指定的任何密码都将成为该帐户的新密码,即使该帐户存在并且已经具有密码。如果没有IDENTIFIED,则帐户密码保持不变。

Global Privileges

全局特权是 Management 性的,或适用于给定服务器上的所有数据库。要分配全局特权,请使用ON *.*语法:

GRANT ALL ON *.* TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON *.* TO 'someuser'@'somehost';

CREATE TABLESPACECREATE USERFILEPROCESSRELOADREPLICATION CLIENTREPLICATION SLAVESHOW DATABASESSHUTDOWNSUPER特权是 Management 特权,只能在全局范围内授予。

其他特权可以全局授予,也可以在更特定的级别授予。

在全局级别授予任何全局特权的GRANT OPTION适用于所有全局特权。

MySQL 将全局特权存储在mysql.user系统 table 中。

Database Privileges

数据库特权适用于给定数据库中的所有对象。要分配数据库级特权,请使用ON db_name.*语法:

GRANT ALL ON mydb.* TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON mydb.* TO 'someuser'@'somehost';

如果使用ON *语法(而不是ON *.*),则会在数据库级别为默认数据库分配特权。如果没有默认数据库,则会发生错误。

可以在数据库级别指定CREATEDROPEVENTGRANT OPTIONLOCK TABLESREFERENCES特权。table 或例程特权也可以在数据库级别指定,在这种情况下,它们适用于数据库中的所有 table 或例程。

MySQL 将数据库特权存储在mysql.db系统 table 中。

Table Privileges

table 特权适用于给定 table 中的所有列。要分配 table 级特权,请使用ON db_name.tbl_name语法:

GRANT ALL ON mydb.mytbl TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON mydb.mytbl TO 'someuser'@'somehost';

如果指定* tbl_name 而不是 db_name.tbl_name ,则该语句适用于默认数据库中的 tbl_name *。如果没有默认数据库,则会发生错误。

table 级别允许的* priv_type *值为ALTERCREATE VIEWCREATEDELETEDROPGRANT OPTIONINDEXINSERTREFERENCESSELECTSHOW VIEWTRIGGERUPDATE

table 级特权适用于基本 table 和视图。它们不适用于使用创建临时 table创建的 table,即使 table 名匹配也是如此。有关TEMPORARYtable 特权的信息,请参见第 13.1.18.2 节“ CREATE TEMPORARY TABLE 语句”

MySQL 将 table 特权存储在mysql.tables_priv系统 table 中。

Column Privileges

列特权适用于给定 table 中的单个列。在列级别要授予的每个特权都必须在括号后加上一个或多个列。

GRANT SELECT (col1), INSERT (col1, col2) ON mydb.mytbl TO 'someuser'@'somehost';

列(即,当您使用* column_list 子句时)允许的 priv_type *值为INSERTREFERENCESSELECTUPDATE

MySQL 将列特权存储在mysql.columns_priv系统 table 中。

存储的常规特权

ALTER ROUTINECREATE ROUTINEEXECUTEGRANT OPTION特权适用于存储的例程(过程和函数)。可以在全局和数据库级别授予它们。除了CREATE ROUTINE之外,可以在例程级别为单个例程授予这些特权。

GRANT CREATE ROUTINE ON mydb.* TO 'someuser'@'somehost';
GRANT EXECUTE ON PROCEDURE mydb.myproc TO 'someuser'@'somehost';

在例程级别允许的priv_type *值为ALTER ROUTINEEXECUTEGRANT OPTIONCREATE ROUTINE不是例程级别的特权,因为您必须具有全局或数据库级别的特权才能首先创建例程。

MySQL 将例程级特权存储在mysql.procs_priv系统 table 中。

代理用户权限

PROXY特权使一个用户可以成为另一个用户的代理。代理用户模拟或获取代理用户的身份;也就是说,它假定了代理用户的特权。

GRANT PROXY ON 'localuser'@'localhost' TO 'externaluser'@'somehost';

授予PROXY时,它必须是GRANT语句中命名的唯一特权,不能提供REQUIRE子句,并且唯一允许的WITH选项是WITH GRANT OPTION

代理要求代理用户通过插件进行身份验证,该插件在代理用户连接时将代理用户的名称返回到服务器,并且代理用户具有代理用户的PROXY特权。有关详细信息和示例,请参见第 6.2.14 节“代理用户”

MySQL 将代理特权存储在mysql.proxies_priv系统 table 中。

隐式帐户创建

如果在GRANT语句中命名的帐户不存在,则采取的操作取决于NO_AUTO_CREATE_USER SQL 模式:

  • 如果未启用NO_AUTO_CREATE_USER,则GRANT创建帐户。 除非您使用IDENTIFIED BY指定非空密码,否则这是非常不安全的

  • 如果启用了NO_AUTO_CREATE_USER,则GRANT失败并且不会创建帐户,除非您使用IDENTIFIED BY指定非空密码或使用IDENTIFIED WITH命名身份验证插件。

如果该帐户已经存在,则禁止IDENTIFIED WITH,因为它仅用于创建新帐户时使用。

其他帐户 Feature

除基于用户名和凭据的常规身份验证外,MySQL 还可以检查 X.509 证书属性。有关在 MySQL 上使用 SSL 的背景信息,请参见第 6.3 节“使用加密的连接”

可选的REQUIRE子句为 MySQL 帐户指定与 SSL 相关的选项。语法与CREATE USER语句相同。有关详细信息,请参见第 13.7.1.2 节“ CREATE USER 语句”

Note

从 MySQL 5.7.6 开始,不再使用GRANT定义帐户 SSL 特性。而是使用CREATE USERALTER USER构建或更改 SSLFeature。 GRANT功能将在将来的 MySQL 版本中删除。

可选的WITH子句用于以下目的:

  • 使用户能够向其他用户授予特权

  • 为用户指定资源限制

WITH GRANT OPTION子句使用户能够将其在指定特权级别上拥有的任何特权授予其他用户。

要为帐户授予GRANT OPTION特权而又不更改其特权,请执行以下操作:

GRANT USAGE ON *.* TO 'someuser'@'somehost' WITH GRANT OPTION;

请向谁授予GRANT OPTION特权,因为具有不同特权的两个用户可能可以组合特权!

您不能授予其他用户您自己没有的特权; GRANT OPTION特权使您只能分配自己拥有的那些特权。

请注意,当您向用户授予特定特权级别的GRANT OPTION特权时,该用户在该级别拥有(或将来可能会授予)的任何特权也可以由该用户授予其他用户。假设您向用户授予数据库的INSERT特权。如果然后在数据库上授予SELECT特权并指定WITH GRANT OPTION,则该用户不仅可以将SELECT特权也可以授予INSERT其他用户。然后,如果您向数据库中的用户授予UPDATE特权,则用户可以授予INSERTSELECTUPDATE

对于非 Management 用户,不应全局授予ALTER特权,也不应授予mysql系统数据库的特权。如果这样做,用户可以尝试通过重命名 table 来破坏特权系统!

有关与特定特权相关的安全风险的其他信息,请参阅第 6.2.2 节“ MySQL 提供的特权”

第 6.2.16 节“设置帐户资源限制”中所述,可以限制帐户对服务器资源的使用。为此,请使用WITH子句指定一个或多个* resource_option *值。未指定的限制将保留其当前值。语法与CREATE USER语句相同。有关详细信息,请参见第 13.7.1.2 节“ CREATE USER 语句”

Note

从 MySQL 5.7.6 开始,不再使用GRANT来定义帐户资源限制。而是使用CREATE USERALTER USER构建或更改资源限制。 GRANT功能将在将来的 MySQL 版本中删除。

GRANT 的 MySQL 和标准 SQL 版本

MySQL 和标准 SQL 版本的GRANT之间的最大区别是:

  • MySQL 将特权与主机名和用户名的组合相关联,而不仅仅是用户名。

  • 标准 SQL 没有全局或数据库级特权,也不支持 MySQL 支持的所有特权类型。

  • MySQL 不支持标准的 SQL UNDER特权。

  • 标准 SQL 特权以分层的方式构造。如果删除用户,则将撤消已授予该用户的所有特权。如果您使用DROP USER,则在 MySQL 中也是如此。参见第 13.7.1.3 节“ DROP USER 语句”

  • 在标准 SQL 中,当您删除 table 时,该 table 的所有特权都将被吊销。在标准 SQL 中,当您撤消特权时,基于该特权授予的所有特权也会被撤消。在 MySQL 中,可以使用DROP USERREVOKE语句删除特权。

  • 在 MySQL 中,可能仅对 table 中的某些列具有INSERT特权。在这种情况下,只要仅为具有INSERT特权的列插入值,您仍可以在 table 上执行INSERT语句。如果未启用严格的 SQL 模式,则省略的列将设置为其隐式默认值。在严格模式下,如果任何省略的列都没有默认值,则该语句将被拒绝。 (标准 SQL 要求您在所有列上都具有INSERT特权。)有关严格 SQL 模式和隐式默认值的信息,请参见第 5.1.10 节“服务器 SQL 模式”第 11.6 节“数据类型默认值”