Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


15.7.1.6 授权语句

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语句必须授予权限或角色。

  • ON子句区分语句是否授予权限或角色:

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

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

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

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

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

GRANT语句要么对所有命名用户和角色成功,要么回滚并无效,如果出现任何错误。该语句只有在所有命名用户和角色都成功时才会写入二进制日志。

REVOKE语句与GRANT相关,用于管理员删除账户权限。请参阅第15.7.1.8节,“REVOKE Statement”

每个帐户名称都使用在第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 语句”

Important

在某些情况下,GRANT 可能会被记录到服务器日志或客户端的历史文件中,如~/.mysql_history,这意味着明文密码可能会被读取由该信息拥有读权限的人。关于服务器日志和控制的条件,以及如何控制,请见第8.1.2.3节,“密码和记录”。关于客户端日志的类似信息,请见第6.5.1.3节,“mysql 客户端记录”

GRANT 支持最长255个字符的主机名。用户名可以是32个字符以下。数据库、表、列和存储程序名称可以是64个字符以下。

Warning

不要尝试通过修改mysql.user系统表来更改可接受的用户名长度。这可能会导致不可预测的行为,甚至使用户无法登录到 MySQL 服务器。从不对mysql系统架构中的表结构进行任何修改,除非按照第3章,《升级 MySQL》中描述的过程。

GRANT 语句中,有些对象需要使用引号,虽然在许多情况下引号是可选的:Account、role、database、table、column 和 routine 名称。例如,如果一个user_namehost_name值在账户名称中是合法的未引号标识符,你不需要引号它。但是,引号是必要的,以指定包含特殊字符(例如-)的user_name字符串或包含特殊字符或通配符(例如%)的host_name字符串。单独引号用户名称和主机名称。

指定引用的值:

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

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

  • 将密码作为字符串引用。

关于字符串引用的指南和标识符引用的指南,请参阅第11.1.1节,“字符串字面量”,和第11.2节,“schema 对象名称”

Important

下面的几个段落中描述的通配符字符%_的使用已经被弃用,因此在 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通配符字符在数据库名称中的出现解释为字面字符,在以下情况下发生:

  • 当数据库名称不用于在数据库级别授予权限,但用作授予某些其他对象(例如表或存储程序)的 qualifier(例如GRANT ... ON db_name.tbl_name)时。

  • 启用partial_revokes 将使 MySQL 将未转义的_%通配符字符在数据库名称中的出现解释为字面字符,就像它们已经被转义为\_partial_revokes的情况下。更多信息,请参见第8.2.12节,“使用部分撤销限制权限”

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

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

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

Note

MySQL 自动将授予给 'username'@'%' 的所有权限授予给 'username'@'localhost' 账户。这一行为已弃用,并且将在 MySQL 未来版本中删除。

MySQL 不支持用户名称中的通配符。要引用匿名用户,请使用GRANT 语句指定一个空用户名称:

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

在这种情况下,任何连接到本地主机并使用正确密码的匿名用户都被允许访问,具有与匿名用户账户关联的权限。

关于帐户名称中的用户名和主机名称值,请参见第8.2.4节,“指定帐户名称”

Warning

如果您允许本地匿名用户连接到 MySQL 服务器,您也应该将所有本地用户授予'user_ name'@'localhost'的权限。否则,当命名用户尝试从本地机器登录到 MySQL 服务器时,MySQL 服务器将使用localhostmysql.user系统表中的匿名用户账户。详细信息请见第8.2.6节,“连接验证,阶段 1:连接验证”

要确定是否存在这个问题,请执行以下查询,该查询列出任何匿名用户:

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

要避免前面描述的问题,请使用以下语句删除本地匿名用户账户:

DROP USER ''@'localhost';

以下表格总结了可以在GRANTREVOKE语句中指定的静态和动态priv_type特权类型,以及每个特权可以在哪些级别上授予。关于每个特权的详细信息,请见第8.2.2节,“MySQL提供的特权”。关于静态和动态特权之间的差异,请见静态 versus 动态特权

表15.11:GRANT和REVOKE语句中的可允许的静态特权

Privilege Meaning and Grantable Levels
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_ 启用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的可允许动态权限

Privilege Meaning and Grantable Levels
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 启用Group Replication控制。级别:全局。
INNODB_REDO_LOG_ARCHIVE 启用 redo 日志归档管理。级别:全局。
INNODB_REDO_LOG_ENABLE 启用或禁用 redo 记录。级别:全局。
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 启用Override默认加密设置。级别:全局。
TELEMETRY_LOG_ADMIN 启用MySQL HeatWave on AWS的telemetry日志配置。级别:全局。
TP_连接_admin 启用线程池连接管理。级别:全局。
版本令牌_admin 启用版本令牌函数使用。级别:全局。
XA_恢复_admin 启用XA RECOVER执行。级别:全局。

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

GRANT语句中,ALL [PRIVILEGES]PROXY特权必须单独指定,而不能与其他特权一起指定。ALL [PRIVILEGES]表示可供在特定级别上授予的所有特权,除了GRANT OPTIONPROXY特权。

MySQL 账户信息存储在 mysql 系统架构的表中。欲了解更多细节,请参阅第8.2节,“Access Control and Account Management”,该节详细讨论了 mysql 系统架构和访问控制系统。

如果授权表中包含混合大小写数据库或表名的特权行,并且lower_case_table_names 系统变量设置为非零值,则REVOKE 语句不能用来撤销这些特权。这种情况下需要直接操作授权表。(GRANT 语句在lower_case_table_names 设置时不会创建这些行,但是在设置该变量之前可能已经创建了这些行。该变量只能在服务器启动时配置。)

特权可以根据用于 ON 子句的语法不同,授予于多个级别上。对于REVOKE 语句,同样使用 ON 子句指定要删除的特权。

在全局、数据库、表和存储程序级别上,GRANT ALL 只分配存在于您正在授予的级别上的权限。例如,GRANT ALL ON db_name.* 是一个数据库级语句,因此不授予任何全局唯一权限,如FILE。授予权限ALL 不分配GRANT OPTIONPROXY 权限。

如果存在,object_类型子句应该指定为 TABLEFUNCTIONPROCEDURE,当以下对象是一个表、存储函数或存储程序时。

用户在数据库、表、列或存储程序上持有的权限是各个权限级别的账户权限的逻辑OR组合,包括全局级别。不能通过在较低级别中缺少该权限来否定在更高级别授予的权限。例如,这个语句授予了SELECTINSERT 权限_globally:

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节,“Access Control, Stage 2: Request Verification”

如果您对任何用户使用表、列或存储过程权限,服务器将检查所有用户的表、列和存储过程权限,这会使MySQL运行速度下降。类似地,如果您限制了任何用户的查询、更新或连接数,服务器必须监控这些值。

MySQL 允许您授予不存在的数据库或表的权限。对于表,需要授予CREATE权限。这是设计行为,旨在使数据库管理员能够为将来创建的数据库或表准备用户账户和权限。

Important

MySQL 不会自动撤销任何权限,当您删除数据库或表时。然而,如果您删除一个存储程序,那么为该存储程序授予的存储程序级别权限将被撤销。

全局权限是管理员权限或对某个服务器上的所有数据库的权限。要分配全局权限,请使用ON *.*语法:

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

CREATE TABLESPACE、CREATE USER、FILE、PROCESS、RELOAD、REPLICATION CLIENT、REPLICATION SLAVE、SHOW DATABASES、SHUTDOWN 和 SUPER 等静态权限是管理员权限,不能在更高级别上授予。

动态权限都是全局权限,不能在更高级别上授予。

其他权限可以在更高级别上授予或授予。

在全局级别授予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 Statement”

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

列权限适用于给定表中的单个列。要授予在列级别的每个权限,必须在括号中将该列或列列表跟随。

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

当使用 column_list 子句时,列 (即 column) 的可允许的 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系统表中。

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

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

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

授予权限不自动激活角色。关于角色激活和停用信息,请见激活角色

授予权限需要以下权限:

  • 如果您拥有ROLE_ADMIN特权(或弃用的SUPER特权),可以将任何角色授予用户或角色。

  • 如果您使用包含GRANT语句的角色授予了一个角色,并且该语句包括WITH ADMIN OPTION子句,您将能够在授予或撤销该角色时授予或撤销其他用户或角色,该角色必须在您授予或撤销时处于活动状态。这还包括使用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

环形授予引用是允许的,但不会向受益者添加新的特权或角色,因为用户或角色已经拥有其特权和角色。

GRANT 语句可以使用一个AS user [WITH ROLE] 子句来指定执行语句时的权限上下文信息。该语法在 SQL 层面可见,但其主要目的是使得部分撤销对 grantor 权限的限制在所有节点上均生效,从而在二进制日志中显示这些限制。关于部分撤销的信息,请参阅第8.2.12节,“使用部分撤销的权限限制”

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

以下条件适用于AS user 子句:

  • AS 只有在命名的user拥有权限限制(这意味着<a class="link" href="server-system-variables.html#sysvar_partial_revokes"><code class="literal">partial_revokes</code></a> 系统变量启用)时才生效。

  • 如果指定了WITH ROLE,那么所有命名的角色都必须授予给命名的user

  • 指定的用户应该是一个 MySQL 账户,格式为'用户名'@'host_name'CURRENT_USERCURRENT_USER()。执行用户可能与WITH ROLE一起指定,以便在执行时使用一组不同的角色集,而不是当前会话中的角色集。

  • AS不能用于获取执行GRANT语句的用户不拥有的权限。执行用户至少需要授予的权限,但AS子句只能限制授予的权限,而不是扩大它们。

  • 在授予权限方面,AS不能指定一个用户/角色组合,该组合拥有执行GRANT语句的用户拥有的更多权限(更少的限制)。执行用户可以拥有更多权限,但只能在语句中不授予这些额外权限时。

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

  • ASPROXY授权不支持。

以下示例演示了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子句只能添加权限限制,而不能escalate权限。因此,虽然u1拥有DELETE权限,但是由于语句没有指定授予DELETE权限,所以不包括在授予的权限中。

  • GRANT 语句中,AS 子句使得角色 r1 对于用户 u1 成为活动的。该角色对 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 权限。

对于非管理员用户,不应该将ALTER权限授予全局或mysql系统架构。如果你这样做,那么用户可以尝试篡改权限系统!

关于特定权限相关的安全风险,见第8.2.2节,“MySQL提供的权限”

MySQL和标准SQL版本GRANT的最大差异是:

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

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

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

  • 标准SQL权限结构化方式是层次式。如果你删除了用户,那么该用户拥有的所有权限都会被撤销。这也适用于在使用DROP USER时的MySQL。如果你想了解更多,请见第15.7.1.5节,“DROP USER Statement”

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

  • 在MySQL中,可以对某些表的某些列授予INSERT权限。在这种情况下,您仍然可以执行INSERT语句,该表,只要您插入的值只包含那些您有INSERT权限的列。省略的列将在非严格SQL模式下设置为隐式默认值。在严格模式下,如果省略的列没有默认值,该语句将被拒绝。 (标准SQL要求您对所有列拥有INSERT权限。)有关严格SQL模式和隐式默认值的信息,请参见第7.1.11节,“服务器SQL模式”第13.6节,“数据类型默认值”