文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


15.7.1.6 GRANT 语句

GRANT
    priv_type [(column_list)]
      [, priv_type [(column_list)]] ...
    ON [object_type] priv_level
    TO user_or_role [, user_or_role] ...
    [WITH GRANT OPTION]
    [AS user
        [WITH ROLE
            DEFAULT
          | NONE
          | ALL
          | ALL EXCEPT role [, role ] ...
          | role [, role ] ...
        ]
    ]
}

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

GRANT role [, role] ...
    TO user_or_role [, user_or_role] ...
    [WITH ADMIN OPTION]

object_type: {
    TABLE
  | FUNCTION
  | PROCEDURE
}

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

user_or_role: {
    user (see Section 8.2.4, “Specifying Account Names”)
  | role (see Section 8.2.5, “Specifying Role Names”)
}

GRANT 语句将权限和角色分配给 MySQL 用户帐户和角色。该 GRANT 语句有几个方面,在以下主题中描述

GRANT 一般概述

GRANT 语句使系统管理员能够授予权限和角色,这些权限和角色可以授予用户帐户和角色。这些语法限制适用

  • GRANT 无法在同一语句中混合授予权限和角色。给定的 GRANT 语句必须授予权限或角色。

  • ON 子句区分语句是授予权限还是角色

    • 使用 ON,该语句授予权限。

    • 不使用 ON,该语句授予角色。

    • 可以将权限和角色分配给同一个帐户,但必须使用单独的 GRANT 语句,每个语句的语法都应适合要授予的内容。

有关角色的更多信息,请参见 第 8.2.10 节“使用角色”

要使用 GRANT 授予权限,您必须拥有 GRANT OPTION 权限,并且您必须拥有要授予的权限。(或者,如果您对 mysql 系统架构中的授权表具有 UPDATE 权限,则可以授予任何帐户任何权限。)当 read_only 系统变量启用时,GRANT 还需要 CONNECTION_ADMIN 权限(或已弃用的 SUPER 权限)。

GRANT 对于所有命名的用户和角色都成功,或者回滚且无任何效果(如果出现任何错误)。如果语句对所有命名的用户和角色都成功,则该语句将写入二进制日志。

REVOKE 语句与 GRANT 相关,使管理员能够删除帐户权限。请参见 第 15.7.1.8 节“REVOKE 语句”

每个帐户名都使用 第 8.2.4 节“指定帐户名” 中描述的格式。每个角色名都使用 第 8.2.5 节“指定角色名” 中描述的格式。例如

GRANT ALL ON db1.* TO 'jeffrey'@'localhost';
GRANT 'role1', 'role2' TO 'user1'@'localhost', 'user2'@'localhost';
GRANT SELECT ON world.* TO 'role3';

如果省略帐户名或角色名的主机名部分,则默认为 '%'

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

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;

mysql 程序中,GRANT 在成功执行时将以 Query OK, 0 rows affected 响应。若要确定操作产生的权限,请使用 SHOW GRANTS。请参见 第 15.7.7.22 节“SHOW GRANTS 语句”

重要

在某些情况下,GRANT 可能记录在服务器日志中或客户端历史文件(如 ~/.mysql_history)中,这意味着任何具有读取访问权限的人员都可以读取明文密码。有关服务器日志中出现这种情况的条件以及如何控制它的信息,请参见 第 8.1.2.3 节“密码和日志记录”。有关客户端日志记录的类似信息,请参见 第 6.5.1.3 节“mysql 客户端日志记录”

GRANT 支持长达 255 个字符的主机名。用户名可以最多 32 个字符。数据库、表、列和例程名称可以最多 64 个字符。

警告

不要尝试通过更改 mysql.user 系统表来更改允许的用户名长度。这样做会导致不可预测的行为,甚至可能导致用户无法登录 MySQL 服务器。决不要以任何方式更改 mysql 系统架构中表的结构,除非使用 第 3 章“升级 MySQL” 中描述的过程。

对象引用指南

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

若要指定引用的值

  • 将数据库、表、列和例程名称引用为标识符。

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

  • 将密码引用为字符串。

有关字符串引用和标识符引用指南,请参见 第 11.1.1 节“字符串文字”第 11.2 节“架构对象名称”

重要

使用通配符 %_(如以下几段中所述)已弃用,因此可能会在 MySQL 的未来版本中删除。

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

发出包含通配符的多个 GRANT 语句可能不会对 DML 语句产生预期效果;在解析涉及通配符的授权时,MySQL 只会考虑第一个匹配的授权。换句话说,如果用户有两个使用通配符匹配同一个数据库的数据库级授权,则会应用第一个创建的授权。考虑使用以下语句创建的数据库 db 和表 t

mysql> CREATE DATABASE db;
Query OK, 1 row affected (0.01 sec)

mysql> CREATE TABLE db.t (c INT);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO db.t VALUES ROW(1);
Query OK, 1 row affected (0.00 sec)

接下来(假设当前帐户是 MySQL root 帐户或具有必要权限的另一个帐户),我们创建用户 u,然后发出两个包含通配符的 GRANT 语句,如下所示

mysql> CREATE USER u;
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT SELECT ON `d_`.* TO u;
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT INSERT ON `d%`.* TO u;
Query OK, 0 rows affected (0.00 sec)

mysql> EXIT
Bye

如果我们结束会话,然后使用 mysql 客户端以 u 的身份再次登录,我们会发现此帐户只有第一个匹配的授权提供的权限,而没有第二个授权提供的权限

$> mysql -uu -hlocalhost
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.4.0-tr Source distribution

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input
statement.

mysql> TABLE db.t;
+------+
| c    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> INSERT INTO db.t VALUES ROW(2);
ERROR 1142 (42000): INSERT command denied to user 'u'@'localhost' for table 't'

在权限分配中,MySQL 在以下情况下将数据库名称中的未转义 _% SQL 通配符解释为文字字符

  • 当数据库名称不用于在数据库级别授予权限,而是用作限定符来授予对其他对象(如表或例程)的权限时(例如,GRANT ... ON db_name.tbl_name)。

  • 启用 partial_revokes 将导致 MySQL 将数据库名称中的未转义 _% 通配符解释为文字字符,就像它们已转义为 \_\% 一样。由于这会更改 MySQL 解释权限的方式,因此建议在 partial_revokes 可能启用的安装中避免在权限分配中使用未转义的通配符。有关更多信息,请参见 第 8.2.12 节“使用部分撤销限制权限”

帐户名

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

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

简单形式 'user_name' 等同于 'user_name'@'%'

注意

MySQL 会自动将授予 'username'@'%' 的所有权限也分配给 'username'@'localhost' 帐户。此行为已弃用,可能会在 MySQL 的未来版本中删除。

MySQL 不支持用户名中的通配符。若要引用匿名用户,请使用 GRANT 语句指定具有空用户名的帐户

GRANT ALL ON test.* TO ''@'localhost' ...;

在这种情况下,任何从本地主机以匿名用户的正确密码连接的用户都将获得访问权限,并具有与匿名用户帐户关联的权限。

有关帐户名中用户名和主机名值的更多信息,请参见 第 8.2.4 节“指定帐户名”

警告

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

若要确定此问题是否适用于您,请执行以下查询,该查询将列出所有匿名用户

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

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

DROP USER ''@'localhost';
MySQL 支持的权限

下表总结了可以在 GRANTREVOKE 语句中指定的允许的静态和动态 priv_type 权限类型,以及可以授予每个权限的级别。有关每个权限的更多信息,请参见 第 8.2.2 节“MySQL 提供的权限”。有关静态权限和动态权限之间差异的信息,请参见 静态权限与动态权限

表 15.11 GRANT 和 REVOKE 允许的静态权限

权限 含义和可授予级别
ALL [PRIVILEGES] 授予指定访问级别下的所有权限,除了 GRANT OPTIONPROXY
ALTER 启用使用 ALTER TABLE。级别:全局、数据库、表。
ALTER ROUTINE 允许更改或删除存储的例程。级别:全局、数据库、例程。
CREATE 启用创建数据库和表。级别:全局、数据库、表。
CREATE ROLE 启用创建角色。级别:全局。
CREATE ROUTINE 启用创建存储的例程。级别:全局、数据库。
CREATE TABLESPACE 启用创建、更改或删除表空间和日志文件组。级别:全局。
CREATE TEMPORARY TABLES 启用使用 CREATE TEMPORARY TABLE。级别:全局、数据库。
CREATE USER 启用使用 CREATE USERDROP USERRENAME USERREVOKE ALL PRIVILEGES。级别:全局。
CREATE VIEW 启用创建或更改视图。级别:全局、数据库、表。
DELETE 启用使用 DELETE。级别:全局、数据库、表。
DROP 启用删除数据库、表和视图。级别:全局、数据库、表。
DROP ROLE 启用删除角色。级别:全局。
EVENT 启用对事件调度器的事件使用。级别:全局、数据库。
EXECUTE 允许用户执行存储的例程。级别:全局、数据库、例程。
FILE 允许用户导致服务器读取或写入文件。级别:全局。
FLUSH_PRIVILEGES 允许用户发出 FLUSH PRIVILEGES 语句。级别:全局。
GRANT OPTION 启用将权限授予或从其他帐户中删除权限。级别:全局、数据库、表、例程、代理。
INDEX 启用创建或删除索引。级别:全局、数据库、表。
INSERT 启用使用 INSERT。级别:全局、数据库、表、列。
LOCK TABLES 启用对您拥有 SELECT 权限的表使用 LOCK TABLES。级别:全局、数据库。
OPTIMIZE_LOCAL_TABLE 启用使用 OPTIMIZE LOCAL TABLEOPTIMIZE NO_WRITE_TO_BINLOG TABLE。级别:全局、数据库、表。
PROCESS 允许用户使用 SHOW PROCESSLIST 查看所有进程。级别:全局。
PROXY 启用用户代理。级别:从用户到用户。
REFERENCES 启用外键创建。级别:全局、数据库、表、列。
RELOAD 启用使用 FLUSH 操作。级别:全局。
REPLICATION CLIENT 允许用户询问源服务器或副本服务器的位置。级别:全局。
REPLICATION SLAVE 允许副本从源读取二进制日志事件。级别:全局。
SELECT 启用使用 SELECT。级别:全局、数据库、表、列。
SHOW DATABASES 启用 SHOW DATABASES 以显示所有数据库。级别:全局。
SHOW VIEW 启用使用 SHOW CREATE VIEW。级别:全局、数据库、表。
SHUTDOWN 启用使用 mysqladmin shutdown。级别:全局。
SUPER 启用使用其他管理操作,例如 CHANGE REPLICATION SOURCE TOKILLPURGE BINARY LOGSSET GLOBALmysqladmin debug 命令。级别:全局。
TRIGGER 启用触发器操作。级别:全局、数据库、表。
UPDATE 启用使用 UPDATE。级别:全局、数据库、表、列。
USAGE 无权限 的同义词

表 15.12 GRANT 和 REVOKE 允许的动态权限

权限 含义和可授予级别
APPLICATION_PASSWORD_ADMIN 启用双密码管理。级别:全局。
AUDIT_ABORT_EXEMPT 允许审计日志过滤器阻止的查询。级别:全局。
AUDIT_ADMIN 启用审计日志配置。级别:全局。
AUTHENTICATION_POLICY_ADMIN 启用身份验证策略管理。级别:全局。
BACKUP_ADMIN 启用备份管理。级别:全局。
BINLOG_ADMIN 启用二进制日志控制。级别:全局。
BINLOG_ENCRYPTION_ADMIN 启用二进制日志加密的激活和停用。级别:全局。
CLONE_ADMIN 启用克隆管理。级别:全局。
CONNECTION_ADMIN 启用连接限制/限制控制。级别:全局。
ENCRYPTION_KEY_ADMIN 启用 InnoDB 密钥轮换。级别:全局。
FIREWALL_ADMIN 启用防火墙规则管理,任何用户。级别:全局。
FIREWALL_EXEMPT 免除用户防火墙限制。级别:全局。
FIREWALL_USER 启用防火墙规则管理,自身。级别:全局。
FLUSH_OPTIMIZER_COSTS 启用优化器成本重新加载。级别:全局。
FLUSH_STATUS 启用状态指示器刷新。级别:全局。
FLUSH_TABLES 启用表刷新。级别:全局。
FLUSH_USER_RESOURCES 启用用户资源刷新。级别:全局。
GROUP_REPLICATION_ADMIN 启用组复制控制。级别:全局。
INNODB_REDO_LOG_ARCHIVE 启用重做日志归档管理。级别:全局。
INNODB_REDO_LOG_ENABLE 启用或禁用重做日志记录。级别:全局。
NDB_STORED_USER 启用在 SQL 节点之间共享用户或角色(NDB 集群)。级别:全局。
PASSWORDLESS_USER_ADMIN 启用无密码用户帐户管理。级别:全局。
PERSIST_RO_VARIABLES_ADMIN 启用持久化只读系统变量。级别:全局。
REPLICATION_APPLIER 充当复制通道的 PRIVILEGE_CHECKS_USER。级别:全局。
REPLICATION_SLAVE_ADMIN 启用常规复制控制。级别:全局。
RESOURCE_GROUP_ADMIN 启用资源组管理。级别:全局。
RESOURCE_GROUP_USER 启用资源组管理。级别:全局。
ROLE_ADMIN 启用授予或撤销角色,使用 WITH ADMIN OPTION。级别:全局。
SESSION_VARIABLES_ADMIN 启用设置受限会话系统变量。级别:全局。
SHOW_ROUTINE 启用访问存储的例程定义。级别:全局。
SKIP_QUERY_REWRITE 不要重写此用户执行的查询。级别:全局。
SYSTEM_USER 指定帐户为系统帐户。级别:全局。
SYSTEM_VARIABLES_ADMIN 启用修改或持久化全局系统变量。级别:全局。
TABLE_ENCRYPTION_ADMIN 启用覆盖默认加密设置。级别:全局。
TELEMETRY_LOG_ADMIN 启用 AWS 上 HeatWave 的遥测日志配置。级别:全局。
TP_CONNECTION_ADMIN 启用线程池连接管理。级别:全局。
VERSION_TOKEN_ADMIN 启用使用版本令牌函数。级别:全局。
XA_RECOVER_ADMIN 启用 XA RECOVER 执行。级别:全局。

触发器与表相关联。要创建或删除触发器,您必须对表拥有 TRIGGER 权限,而不是对触发器。

GRANT 语句中,ALL [PRIVILEGES]PROXY 权限必须单独命名,不能与其他权限一起指定。 ALL [PRIVILEGES] 代表要授予权限级别的所有可用权限,除了 GRANT OPTIONPROXY 权限。

MySQL 帐户信息存储在 mysql 系统模式的表中。有关更多详细信息,请参阅 第 8.2 节,“访问控制和帐户管理”,其中详细讨论了 mysql 系统模式和访问控制系统。

如果授予表包含包含大小写混合的数据库或表名称的权限行,并且 lower_case_table_names 系统变量设置为非零值,则 REVOKE 无法用于撤销这些权限。在这种情况下,必须直接操作授予表。(当 lower_case_table_names 设置时,GRANT 不会创建此类行,但此类行可能在设置该变量之前创建。 lower_case_table_names 设置只能在服务器启动时配置。)

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

对于全局、数据库、表和例程级别,GRANT ALL 仅分配存在于您授予权限级别的权限。例如,GRANT ALL ON db_name.* 是一个数据库级语句,因此它不会授予任何全局专用权限,例如 FILE。授予 ALL 不会分配 GRANT OPTIONPROXY 权限。

如果存在,object_type 子句应指定为 TABLEFUNCTIONPROCEDURE,当以下对象是表、存储函数或存储过程时。

用户对数据库、表、列或例程拥有的权限是作为每个权限级别(包括全局级别)的帐户权限的逻辑 OR 累加形成的。不可能通过缺少更低级别的权限来拒绝在更高级别授予的权限。例如,此语句在全局范围内授予 SELECTINSERT 权限

GRANT SELECT, INSERT ON *.* TO u1;

全局授予的权限适用于所有数据库、表和列,即使没有在任何这些较低级别授予。

如果partial_revokes系统变量已启用,则可以通过撤销特定数据库的全局权限来显式拒绝该权限。

GRANT SELECT, INSERT, UPDATE ON *.* TO u1;
REVOKE INSERT, UPDATE ON db1.* FROM u1;

上述语句的结果是,SELECT在全局范围内适用于所有表,而INSERTUPDATE在全局范围内适用,但db1中的表除外。帐户对db1的访问权限为只读。

权限检查过程的详细信息见第 8.2.7 节“访问控制,阶段 2:请求验证”

如果即使对一个用户使用表、列或例程权限,服务器也会检查所有用户的表、列和例程权限,这会稍微降低 MySQL 的速度。类似地,如果限制任何用户的查询、更新或连接数量,服务器必须监控这些值。

MySQL 允许您在不存在的数据库或表上授予权限。对于表,要授予的权限必须包括CREATE权限。这种行为是设计使然,其目的是使数据库管理员能够为以后要创建的数据库或表准备用户帐户和权限。

重要

当您删除数据库或表时,MySQL 不会自动撤销任何权限。但是,如果您删除例程,则为该例程授予的任何例程级权限都会被撤销。

全局权限

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

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

CREATE TABLESPACECREATE USERFILEPROCESSRELOADREPLICATION CLIENTREPLICATION SLAVESHOW DATABASESSHUTDOWNSUPER静态权限是管理权限,只能在全局范围内授予。

动态权限都是全局的,只能在全局范围内授予。

其他权限可以在全局范围内或在更具体的级别授予。

在全局级别授予GRANT OPTION对静态权限和动态权限的影响不同。

  • 为任何静态全局权限授予的GRANT OPTION适用于所有静态全局权限。

  • 为任何动态权限授予的GRANT OPTION仅适用于该动态权限。

在全局级别授予GRANT ALL会授予所有静态全局权限和所有当前注册的动态权限。在执行GRANT语句后注册的动态权限不会追溯授予任何帐户。

MySQL 将全局权限存储在mysql.user系统表中。

数据库权限

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

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

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

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

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

表权限

表权限适用于给定表中的所有列。要分配表级权限,请使用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。如果不存在默认数据库,则会发生错误。

在表级别允许的priv_type值为ALTERCREATE VIEWCREATEDELETEDROPGRANT OPTIONINDEXINSERTREFERENCESSELECTSHOW VIEWTRIGGERUPDATE

表级权限适用于基本表和视图。它们不适用于使用CREATE TEMPORARY TABLE创建的表,即使表名匹配。有关TEMPORARY表权限的信息,请参见第 15.1.20.2 节“CREATE TEMPORARY TABLE 语句”

MySQL 将表权限存储在mysql.tables_priv系统表中。

列权限

列权限适用于给定表中的单个列。在列级别要授予的每个权限后面都必须加上用括号括起来的列名。

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

在列级别(即当您使用column_list子句时)允许的priv_type值为INSERTREFERENCESSELECTUPDATE

MySQL 将列权限存储在mysql.columns_priv系统表中。

存储例程权限

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系统表中。

代理用户权限

PROXY权限使一个用户可以充当另一个用户的代理。代理用户模拟或假冒被代理用户的身份;也就是说,它假设被代理用户的权限。

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

当授予PROXY时,它必须是GRANT语句中命名的唯一权限,并且唯一允许的WITH选项是WITH GRANT OPTION

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

MySQL 将代理权限存储在mysql.proxies_priv系统表中。

授予角色

没有ON子句的GRANT语法授予角色而不是单个权限。角色是权限的命名集合;请参见第 8.2.10 节“使用角色”。例如

GRANT 'role1', 'role2' TO 'user1'@'localhost', 'user2'@'localhost';

要授予的每个角色都必须存在,以及要授予它的每个用户帐户或角色。角色不能授予匿名用户。

授予角色不会自动导致角色处于活动状态。有关角色激活和停用的信息,请参见激活角色

需要这些权限才能授予角色

  • 如果您具有ROLE_ADMIN权限(或已弃用的SUPER权限),则可以向用户或角色授予或撤销任何角色。

  • 如果您使用包含WITH ADMIN OPTION子句的GRANT语句授予了角色,则您将能够向其他用户或角色授予该角色,或从其他用户或角色撤销该角色,只要该角色在您随后授予或撤销该角色时处于活动状态。这包括使用WITH ADMIN OPTION本身的能力。

  • 要授予具有SYSTEM_USER权限的角色,您必须具有SYSTEM_USER权限。

可以使用GRANT创建循环引用。例如

CREATE USER 'u1', 'u2';
CREATE ROLE 'r1', 'r2';

GRANT 'u1' TO 'u1';   -- simple loop: u1 => u1
GRANT 'r1' TO 'r1';   -- simple loop: r1 => r1

GRANT 'r2' TO 'u2';
GRANT 'u2' TO 'r2';   -- mixed user/role loop: u2 => r2 => u2

允许循环授予引用,但不会向被授予者添加任何新的权限或角色,因为用户或角色已经拥有其权限和角色。

AS子句和权限限制

GRANT可以使用AS user [WITH ROLE]子句来指定有关用于语句执行的权限上下文的附加信息。这种语法在 SQL 级别可见,尽管它的主要目的是通过使这些限制出现在二进制日志中,从而在所有授予者权限限制(由部分撤销强加)的所有节点上实现统一的复制。有关部分撤销的信息,请参见第 8.2.12 节“使用部分撤销限制权限”

当指定 AS user 子句时,语句执行会考虑与指定用户关联的任何权限限制,包括 WITH ROLE 指定的所有角色(如果存在)。结果是,语句实际授予的权限可能会相对于指定权限减少。

这些条件适用于 AS user 子句

  • AS 仅在指定 user 具有权限限制时才生效(这意味着 partial_revokes 系统变量已启用)。

  • 如果给出 WITH ROLE,则必须将所有命名的角色授予指定 user

  • 指定 user 应为一个 MySQL 帐户,指定为 'user_name'@'host_name'CURRENT_USERCURRENT_USER()。当前用户可以与 WITH ROLE 一起命名,以防执行用户希望 GRANT 使用一组应用于当前会话中处于活动状态的角色不同的角色执行。

  • AS 不能用于获取执行 GRANT 语句的用户所不拥有的权限。执行用户必须至少拥有要授予的权限,但 AS 子句只能限制授予的权限,而不能提升它们。

  • 关于要授予的权限,AS 不能指定拥有比执行 GRANT 语句的用户更多权限(更少的限制)的用户/角色组合。允许 AS 用户/角色组合拥有比执行用户更多的权限,但前提是语句未授予这些额外的权限。

  • AS 仅支持授予全局权限(ON *.*)。

  • AS 不支持 PROXY 授权。

以下示例说明了 AS 子句的效果。创建一个用户 u1,该用户拥有某些全局权限以及对这些权限的限制

CREATE USER u1;
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
REVOKE INSERT, UPDATE ON schema1.* FROM u1;
REVOKE SELECT ON schema2.* FROM u1;

还创建一个角色 r1,该角色取消了某些权限限制并将该角色授予 u1

CREATE ROLE r1;
GRANT INSERT ON schema1.* TO r1;
GRANT SELECT ON schema2.* TO r1;
GRANT r1 TO u1;

现在,使用没有自身权限限制的帐户,向多个用户授予相同的全局权限集,但每个用户都通过 AS 子句施加不同的限制,并检查实际授予的权限。

  • 此处的 GRANT 语句没有 AS 子句,因此授予的权限与指定权限完全相同

    mysql> CREATE USER u2;
    mysql> GRANT SELECT, INSERT, UPDATE ON *.* TO u2;
    mysql> SHOW GRANTS FOR u2;
    +-------------------------------------------------+
    | Grants for u2@%                                 |
    +-------------------------------------------------+
    | GRANT SELECT, INSERT, UPDATE ON *.* TO `u2`@`%` |
    +-------------------------------------------------+
  • 此处的 GRANT 语句有一个 AS 子句,因此授予的权限是指定的权限,但应用了来自 u1 的限制

    mysql> CREATE USER u3;
    mysql> GRANT SELECT, INSERT, UPDATE ON *.* TO u3 AS u1;
    mysql> SHOW GRANTS FOR u3;
    +----------------------------------------------------+
    | Grants for u3@%                                    |
    +----------------------------------------------------+
    | GRANT SELECT, INSERT, UPDATE ON *.* TO `u3`@`%`    |
    | REVOKE INSERT, UPDATE ON `schema1`.* FROM `u3`@`%` |
    | REVOKE SELECT ON `schema2`.* FROM `u3`@`%`         |
    +----------------------------------------------------+

    如前所述,AS 子句只能添加权限限制;它不能提升权限。因此,虽然 u1 具有 DELETE 权限,但由于语句未指定授予 DELETE,因此不包括在授予的权限中。

  • 此处的 GRANT 语句的 AS 子句使角色 r1u1 处于活动状态。该角色取消了对 u1 的一些限制。因此,授予的权限有一些限制,但不像以前 GRANT 语句那样多

    mysql> CREATE USER u4;
    mysql> GRANT SELECT, INSERT, UPDATE ON *.* TO u4 AS u1 WITH ROLE r1;
    mysql> SHOW GRANTS FOR u4;
    +-------------------------------------------------+
    | Grants for u4@%                                 |
    +-------------------------------------------------+
    | GRANT SELECT, INSERT, UPDATE ON *.* TO `u4`@`%` |
    | REVOKE UPDATE ON `schema1`.* FROM `u4`@`%`      |
    +-------------------------------------------------+

如果 GRANT 语句包含 AS user 子句,则会忽略执行语句的用户对权限的限制(而不是像没有 AS 子句时那样应用)。

其他帐户特征

可选 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

对于非管理员用户,您不应全局或针对 mysql 系统架构授予 ALTER 权限。如果您这样做,用户可能会尝试通过重命名表来破坏权限系统!

有关与特定权限相关的安全风险的更多信息,请参阅 第 8.2.2 节,“MySQL 提供的权限”

MySQL 和标准 SQL 版本的 GRANT

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

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

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

  • MySQL 不支持标准 SQL UNDER 权限。

  • 标准 SQL 权限以层次结构方式构建。如果您删除用户,则该用户被授予的所有权限都会被撤销。如果您使用 DROP USER,MySQL 中也是如此。请参阅 第 15.7.1.5 节,“DROP USER 语句”

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

  • 在 MySQL 中,可以对表中仅某些列拥有 INSERT 权限。在这种情况下,您仍然可以对表执行 INSERT 语句,前提是您仅为拥有 INSERT 权限的列插入值。如果未启用严格 SQL 模式,则将省略的列设置为其隐式默认值。在严格模式下,如果任何省略的列没有默认值,则语句将被拒绝。(标准 SQL 要求您对所有列拥有 INSERT 权限。)有关严格 SQL 模式和隐式默认值的更多信息,请参阅 第 7.1.11 节,“服务器 SQL 模式”第 13.6 节,“数据类型默认值”