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
语句使系统管理员能够授予权限和角色,这些权限和角色可以授予用户账户和角色。这些语法限制适用:
有关角色的更多信息,请参阅 第 8.2.10 节,“使用角色”。
要使用 GRANT
授予权限,您必须拥有 GRANT OPTION
权限,并且您必须拥有要授予的权限。(或者,如果您拥有 UPDATE
权限对 mysql
系统架构中的授权表,您可以授予任何账户任何权限。)当 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_name
或 host_name
值在账户名称中是合法的未引用的标识符,你不需要引用它们。然而,引号是指定包含特殊字符(例如 -
)的 user_name
字符串或包含特殊字符或通配符(例如 %
)的 host_name
字符串(例如 'test-user'@'%.com'
)所必需的。
要指定引用的值:
-
将数据库、表、列和例程名称作为标识符引用。
-
将用户名和主机名作为标识符或字符串引用。
-
将密码作为字符串引用。
有关字符串引用和标识符引用的指南,请见 第 11.1.1 节,“字符串字面量” 和 第 11.2 节,“模式对象名称”。
使用通配符 %
和 _
,如下几段落所述,从 MySQL 8.2.0 开始弃用,可能在未来版本的 MySQL 中删除。
在 GRANT
语句中,允许在数据库名称中使用 _
和 %
通配符,以授予数据库级别的权限(GRANT ... ON
)。例如,要在数据库名称中使用 db_name
.*_
字符,需要使用 \
转义字符,如 \_
,以防止用户访问其他匹配通配符模式的数据库(例如,GRANT ... ON `foo\_bar`.* TO ...
)。
发出多个包含通配符的 GRANT
语句可能不会产生预期的效果;在解析包含通配符的授予权限时,MySQL 只考虑第一个匹配的授予权限。换言之,如果用户拥有两个使用通配符的数据库级别授予权限,MySQL 将应用第一个创建的授予权限。
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.3.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
值的形式为 '
。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
'@'%'
MySQL 自动将授予 '
的所有权限分配给 username
'@'%''
账户。该行为在 MySQL 8.0.35 及更高版本中弃用,可能在未来版本的 MySQL 中删除。username
'@'localhost'
MySQL 不支持用户名中的通配符. 要引用匿名用户,请使用 GRANT
语句指定一个空用户名的账户:
GRANT ALL ON test.* TO ''@'localhost' ...;
在这种情况下,任何从本地主机连接的用户,如果提供了匿名用户的正确密码,将被授予访问权限,具有与匿名用户账户相关的权限。
有关账户名称和主机名值的更多信息,请参阅 第 8.2.4 节,“指定账户名称”。
如果您允许本地匿名用户连接到 MySQL 服务器,也应该授予所有本地用户 '
的权限。否则,当命名用户尝试从本地机器登录到 MySQL 服务器时,将使用 user_name
'@'localhost'mysql.user
系统表中的匿名用户账户。有关详细信息,请参阅 第 8.2.6 节,“访问控制,阶段 1:连接验证”。
要确定是否适用此问题,请执行以下查询,该查询将列出所有匿名用户:
SELECT Host, User FROM mysql.user WHERE User='';
要避免上述问题,请使用以下语句删除本地匿名用户账户:
DROP USER ''@'localhost';
以下表格总结了可以为 GRANT
和 REVOKE
语句指定的静态和动态 priv_type
权限类型,以及每个权限可以授予的级别。有关每个权限的更多信息,请参阅 第 8.2.2 节,“MySQL 提供的权限”。有关静态和动态权限之间的差异,请参阅 静态与动态权限。
表 15.11 GRANT 和 REVOKE 的可授予静态权限
Privilege | Meaning and Grantable Levels |
---|---|
ALL [PRIVILEGES] |
授予指定访问级别的所有权限,除了 GRANT OPTION 和 PROXY 。 |
ALTER |
启用 ALTER TABLE 的使用。级别:Global、数据库、表。 |
ALTER ROUTINE |
启用存储过程的修改或删除。级别:Global、数据库、过程。 |
CREATE |
启用数据库和表的创建。级别:Global、数据库、表。 |
CREATE ROLE |
启用角色创建。级别:Global。 |
CREATE ROUTINE |
启用存储过程的创建。级别:Global、数据库。 |
CREATE TABLESPACE |
启用表空间和日志文件组的创建、修改或删除。级别:Global。 |
CREATE TEMPORARY TABLES |
启用 CREATE TEMPORARY TABLE 的使用。级别:Global、数据库。 |
CREATE USER |
启用 CREATE USER 、DROP USER 、RENAME USER 和 REVOKE ALL PRIVILEGES 的使用。级别:Global。 |
CREATE VIEW |
启用视图的创建或修改。级别:Global、数据库、表。 |
删除 |
启用 删除 。级别:Global、数据库、表。 |
DROP |
启用数据库、表和视图的删除。级别:Global、数据库、表。 |
DROP ROLE |
启用角色删除。级别:Global。 |
EVENT |
启用事件计划器的使用。级别:Global、数据库。 |
EXECUTE |
启用存储过程的执行。级别:Global、数据库、过程。 |
FILE |
启用服务器读取或写入文件的能力。级别:Global。 |
GRANT OPTION |
启用权限的授予或撤销。级别:Global、数据库、表、过程、代理。 |
INDEX |
启用索引的创建或删除。级别:Global、数据库、表。 |
INSERT |
启用 INSERT 。级别:Global、数据库、表、列。 |
LOCK TABLES |
启用 LOCK TABLES 在拥有 SELECT 权限的表上。级别:Global、数据库。 |
PROCESS |
启用所有进程的查看,使用 SHOW PROCESSLIST 。级别:Global。 |
PROXY |
启用用户代理。级别:从用户到用户。 |
REFERENCES |
启用外键的创建。级别:Global、数据库、表、列。 |
RELOAD |
启用 FLUSH 操作。级别:Global。 |
REPLICATION CLIENT |
启用源或副本服务器的查询。级别:Global。 |
REPLICATION SLAVE |
启用副本从源服务器读取二进制日志事件。级别:Global。 |
SELECT |
启用 SELECT 。级别:Global、数据库、表、列。 |
SHOW DATABASES |
启用 SHOW DATABASES 显示所有数据库。级别:Global。 |
SHOW VIEW |
启用 SHOW CREATE VIEW 。级别:Global、数据库、表。 |
SHUTDOWN |
启用 mysqladmin shutdown。级别:Global。 |
SUPER |
启用其他管理操作,如 更改复制源到 , KILL , PURGE 二进制日志 , SET 全局 ,和 mysqladmin 调试 命令。级别:全局。 |
触发器 |
启用触发器操作。级别:全局、数据库、表。 |
更新 |
启用 UPDATE 。级别:全局、数据库、表、列。 |
使用 |
同义词“无权限”。 |
表 15.12 GRANT 和 REVOKE 的可授予动态权限
Privilege | Meaning and Grantable Levels |
---|---|
应用程序密码管理员 |
启用双密码管理。级别:全局。 |
审核中止豁免 |
允许查询被审核日志过滤器阻止。级别:全局。 |
审核管理员 |
启用审核日志配置。级别:全局。 |
身份验证策略管理员 |
启用身份验证策略管理。级别:全局。 |
备份管理员 |
启用备份管理。级别:全局。 |
二进制日志管理员 |
启用二进制日志控制。级别:全局。 |
二进制日志加密管理员 |
启用二进制日志加密激活和停用。级别:全局。 |
克隆管理员 |
启用克隆管理。级别:全局。 |
连接管理员 |
启用连接限制/限制控制。级别:全局。 |
加密密钥管理员 |
启用 InnoDB 密钥轮换。级别:全局。 |
防火墙管理员 |
启用防火墙规则管理,任何用户。级别:全局。 |
防火墙豁免 |
豁免用户防火墙限制。级别:全局。 |
防火墙用户 |
启用防火墙规则管理,自己。级别:全局。 |
刷新优化器成本 |
启用优化器成本重新加载。级别:全局。 |
刷新状态 |
启用状态指示符刷新。级别:全局。 |
刷新表 |
启用表刷新。级别:全局。 |
刷新用户资源 |
启用用户资源刷新。级别:全局。 |
组复制管理员 |
启用组复制控制。级别:全局。 |
InnoDB 重做日志存档 |
启用重做日志存档管理。级别:全局。 |
InnoDB 重做日志启用 |
启用或禁用重做日志记录。级别:全局。 |
NDB_STORED_USER |
在 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 |
启用设置受限的会话系统变量。级别:全局。 |
SET_USER_ID |
启用设置非自身 DEFINER 值。级别:全局。 |
SHOW_ROUTINE |
启用存储过程定义的访问。级别:全局。 |
SKIP_QUERY_REWRITE |
不重写由该用户执行的查询。级别:全局。 |
SYSTEM_USER |
指定账户为系统账户。级别:全局。 |
SYSTEM_VARIABLES_ADMIN |
启用修改或持久化全局系统变量。级别:全局。 |
TABLE_ENCRYPTION_ADMIN |
启用覆盖默认加密设置。级别:全局。 |
TELEMETRY_LOG_ADMIN |
启用 MySQL HeatWave on AWS 的遥测日志配置。级别:全局。 |
TP_CONNECTION_ADMIN |
启用线程池连接管理。级别:全局。 |
VERSION_TOKEN_ADMIN |
启用版本令牌函数。级别:全局。 |
XA_RECOVER_ADMIN |
启用 XA RECOVER 执行。级别:全局。 |
触发器与表关联。要创建或删除触发器,必须拥有该表的 TRIGGER
权限,而不是触发器。
在 GRANT
语句中,ALL [PRIVILEGES]
或 PROXY
权限必须单独命名,不能与其他权限一起指定。ALL [PRIVILEGES]
代表授予级别的所有权限,除了 GRANT OPTION
和 PROXY
权限。
MySQL 账户信息存储在 mysql
系统模式的表中。有关详细信息,请参阅 第 8.2 节,“访问控制和账户管理”,其中讨论了 mysql
系统模式和访问控制系统。
如果授权表包含混合大小写数据库或表名的特权行,并且 lower_case_table_names
系统变量设置为非零值,则无法使用 REVOKE
撤销这些特权。在这种情况下,需要直接操作授权表。(GRANT
不会在 lower_case_table_names
设置时创建这些行,但这些行可能是在设置该变量之前创建的。 lower_case_table_names
设置只能在服务器启动时配置。)
特权可以在多个级别授予,具体取决于 ON
子句的语法。对于 REVOKE
,相同的 ON
语法指定要撤销的特权。
对于全局、数据库、表和例程级别,GRANT ALL
只分配该级别存在的特权。例如,GRANT ALL ON
是一个数据库级别语句,因此它不授予任何全局级别特权,如 db_name
.*FILE
。授予 ALL
不会分配 GRANT OPTION
或 PROXY
特权。
如果存在,object_type
子句应指定为 TABLE
、FUNCTION
或 PROCEDURE
,具体取决于后面的对象是表、存储函数还是存储过程。
用户在数据库、表、列或例程上的特权是通过在每个特权级别(包括全局级别)的账户特权的逻辑 OR
运算符形成的。无法通过在较低级别缺少特权来否定较高级别授予的特权。例如,以下语句授予全局 SELECT
和 INSERT
特权:
GRANT SELECT, INSERT ON *.* TO u1;
全局授予的特权适用于所有数据库、表和列,即使没有在这些较低级别授予。
如果启用了 partial_revokes
系统变量,可以通过撤销特定数据库的特权来明确否定全局级别授予的特权:
GRANT SELECT, INSERT, UPDATE ON *.* TO u1;
REVOKE INSERT, UPDATE ON db1.* FROM u1;
前面的语句的结果是 SELECT
适用于所有表,而 INSERT
和 UPDATE
适用于除 db1
之外的所有表。db1
的账户访问是只读的。
特权检查过程的详细信息请参阅 第 8.2.7 节,“访问控制,第二阶段:请求验证”。
如果您为任何用户使用表、列或例程特权,服务器将检查所有用户的表、列和例程特权,这将使 MySQL 变慢。类似地,如果您限制了任何用户的查询、更新或连接数,服务器必须监控这些值。
MySQL 允许您授予不存在的数据库或表的特权。对于表,授予的特权必须包括 CREATE
特权。这是设计的意图,旨在使数据库管理员能够为将来创建的数据库或表准备用户账户和特权。
MySQL 不会在删除数据库或表时自动撤销任何权限。然而,如果您删除一个routine,任何授予该routine的routine级权限将被撤销。
全局权限是管理或应用于服务器上的所有数据库的权限。要分配全局权限,请使用 ON *.*
语法:
GRANT ALL ON *.* TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON *.* TO 'someuser'@'somehost';
The 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 *.*
),权限将被授予默认数据库的数据库级别。如果没有默认数据库,将发生错误。
The CREATE
, DROP
, EVENT
, GRANT OPTION
, LOCK TABLES
, 和 REFERENCES
权限可以在数据库级别指定。表或routine权限也可以在数据库级别指定,在这种情况下它们将应用于数据库中的所有表或routine。
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
值在表级别是 ALTER
、CREATE VIEW
、CREATE
、DELETE
、DROP
、GRANT OPTION
、INDEX
、INSERT
、REFERENCES
、SELECT
、SHOW VIEW
、TRIGGER
和 UPDATE
。
表级别权限适用于基本表和视图,不适用于使用 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
子句)是 INSERT
、REFERENCES
、SELECT
和 UPDATE
。
MySQL 将列权限存储在 mysql.columns_priv
系统表中。
The ALTER ROUTINE
、CREATE ROUTINE
、EXECUTE
和 GRANT OPTION
权限适用于存储例程(过程和函数)。它们可以在全局和数据库级别授予。除了 CREATE ROUTINE
之外,这些权限可以在单个例程级别授予。
GRANT CREATE ROUTINE ON mydb.* TO 'someuser'@'somehost';
GRANT EXECUTE ON PROCEDURE mydb.myproc TO 'someuser'@'somehost';
允许的 priv_type
值在例程级别是 ALTER ROUTINE
、EXECUTE
和 GRANT OPTION
。CREATE ROUTINE
不是例程级别权限,因为您必须在全局或数据库级别拥有该权限才能创建例程。
MySQL 将例程级别权限存储在 mysql.procs_priv
系统表中。
The 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
子句,那么您将能够授予该角色给其他用户或角色,或者从其他用户或角色撤销该角色,只要该角色在授予或撤销时处于活动状态。 -
要授予拥有
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
子句指定关于权限上下文的附加信息,以便语句执行。该语法在 SQL 级别可见,尽管其主要目的是为了在所有节点上实现统一的复制,跨所有节点实施部分撤销的权限限制,并将这些限制显示在二进制日志中。有关部分撤销的信息,请参阅第 8.2.12 节,“使用部分撤销的权限限制”。user
[WITH ROLE]
当指定AS
子句时,语句执行将考虑到该用户关联的权限限制,包括所有使用user
WITH ROLE
指定的角色。结果是,语句授予的权限可能相比指定的权限减少。
以下条件适用于AS
子句:user
-
AS
子句仅在命名的user
拥有权限限制时生效(这意味着partial_revokes
系统变量启用)。 -
如果给定
WITH ROLE
,则所有命名的角色都必须授予该命名的user
。 -
命名的
用户
应该是指定的 MySQL 帐户,例如'
,用户名
'@'主机名
'CURRENT_USER
,或CURRENT_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
权限。 -
这里的
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
子句,执行用户的权限限制将被忽略(而不是像没有 用户
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
权限,该用户可以授予INSERT
、SELECT
和UPDATE
权限。
对于非管理员用户,不应授予ALTER
权限全局或对mysql
系统架构。如果您这样做,该用户可以尝试破坏权限系统通过重命名表格!
有关特定权限相关的安全风险的更多信息,请参阅第 8.2.2 节,“MySQL 提供的权限”。
MySQL 和标准 SQL 版本的 GRANT 之间最大的区别是:
-
MySQL 将权限与主机名和用户名的组合关联,而不是仅与用户名关联。
-
标准 SQL 不具有全局或数据库级别的权限,也不支持 MySQL 支持的所有权限类型。
-
MySQL 不支持标准 SQL 的
UNDER
权限。 -
标准 SQL 权限以层次结构组织。如果您删除用户,所有授予该用户的权限都将被撤销。这也是 MySQL 中的真实情况,如果您使用
DROP USER
。请参阅 第 15.7.1.5 节,“DROP USER 语句”。 -
在标准 SQL 中,当您删除表格时,所有表格权限都将被撤销。在标准 SQL 中,当您撤销权限时,基于该权限授予的所有权限也将被撤销。在 MySQL 中,权限可以使用
DROP USER
或REVOKE
语句撤销。 -
在 MySQL 中,您可以拥有表格中某些列的
INSERT
权限。在这种情况下,您可以执行INSERT
语句,只要您插入的值仅为您拥有INSERT
权限的那些列。省略的列将设置为其隐式默认值,如果严格 SQL 模式未启用。在严格模式下,如果省略的列没有默认值,语句将被拒绝。(标准 SQL 要求您在所有列上拥有INSERT
权限。)有关严格 SQL 模式和隐式默认值的信息,请参阅 第 7.1.11 节,“服务器 SQL 模式” 和 第 13.6 节,“数据类型默认值”。