文档首页
MySQL 9.0 参考手册
相关文档 下载此手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
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”)
}

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

GRANT 一般概述

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

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

  • The 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: 9.1.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 服务器时,将使用 mysql.user 系统表中 localhost 的匿名用户账户。有关详细信息,请参见 第 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 无法用于撤销这些权限。在这种情况下,必须直接操作授予表。(GRANTlower_case_table_names 设置时不会创建这样的行,但这样的行可能是在设置该变量之前创建的。 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';

列允许的 priv_type 值(即,当您使用 column_list 子句时)是 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 子句为 u1 激活角色 r1。该角色消除了 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 节,“数据类型默认值”