Mysql 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 
  | role 
}


GRANT总览

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


  • GRANT语句不能在同一语句中同时授予权限和角色。给定的GRANT语句必须授予权限或角色之一。
  • ON子句区分语句是授予权限还是角色:
    • 使用ON,语句授予权限。
    • 不使用ON,语句授予角色。


允许将权限和角色都分配给一个账户,但必须使用单独的GRANT语句,每个语句的语法与所要授予的内容相匹配。


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


GRANT要么对所有已命名的用户和角色成功,要么回滚并且如果发生任何错误则不产生影响。只有当对所有已命名的用户和角色都成功后,该语句才会被写入二进制日志。


REVOKE语句与GRANT有关,它使管理员能够撤销账户权限。


例如:

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。


重要提示
某些情况下,GRANT命令可能会被记录在服务器日志中或客户端的历史文件中,比如~/.mysql_history,这意味着明文密码可能被任何拥有读取权限的人读取。


GRANT命令支持主机名最长可以达到255个字符(在MySQL 8.0.17之前为60个字符)。用户名最长可以达到32个字符。数据库、表、列和例程名称的长度可以达到64个字符。


警告
不要尝试通过修改mysql.user系统表的方式来改变用户名的允许长度。这样做会导致不可预测的行为,甚至可能导致用户无法登录MySQL服务器。


对象引用指南

在GRANT语句中,几个对象需要进行引用,尽管在许多情况下引用是可选的:账户、角色、数据库、表、列和例程名称。例如,如果一个账户名称中的user_name或host_name值作为非引用标识符是合法的,那么你不需要对其进行引用。然而,当指定包含特殊字符(如 -)的user_name字符串或包含特殊字符或通配符字符(如 %)的host_name字符串时,引号是必需的(例如,'test-user'@'%.com')。分别引用用户名称和主机名。


要指定引用值:

  • 将数据库、表、列和例程名称引用为标识符。
  • 将用户名称和主机名引用为标识符或字符串。
  • 将密码引用为字符串。


在授予数据库级权限的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.0.35-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 的安装中避免使用未转义的通配符字符进行授权分配。


账户名

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


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


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


MySQL不支持在用户名中使用通配符。要引用匿名用户,请使用带有空用户名的账户在GRANT语句中进行设置:

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


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


警告
如果允许本地匿名用户连接到MySQL服务器,您还应授予所有本地用户作为'user_name'@'localhost'的权限。否则,当命名用户尝试从本地计算机登录到MySQL服务器时,将使用mysql.user系统表中localhost的匿名用户账户。


要确定是否适用此问题,请执行以下查询,列出任何匿名用户:

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


为避免刚才描述的问题,使用以下语句删除本地匿名用户账户:

DROP USER @'localhost';


MySQL支持的权限

以下表总结了可以在GRANT和REVOKE语句中指定的可以使用的静态(priv_type)和动态(priv_type)权限类型,以及可以授予每个权限的级别。


静态权限

  • ALL 允许在指定的访问级别下授予除了GRANT OPTION和PROXY之外的所有权限。


  • ALTER 允许使用ALTER TABLE。级别:全局、数据库、表。


  • ALTER ROUTINE 允许修改或删除存储过程。级别:全局、数据库、例程。


  • CREATE 允许创建数据库和表。级别:全局、数据库、表。


  • CREATE ROLE 允许创建角色。级别:全局。


  • CREATE ROUTINE 允许创建存储过程。级别:全局、数据库。


  • CREATE TABLESPACE 允许创建、修改或删除表空间和日志文件组。级别:全局。


  • CREATE TEMPORARY TABLES 允许使用CREATE TEMPORARY TABLE。级别:全局、数据库。


  • CREATE USER 允许使用CREATE USER、DROP USER、RENAME USER和REVOKE ALL PRIVILEGES。级别:全局。


  • CREATE VIEW 允许创建或修改视图。级别:全局、数据库、表。


  • DELETE 允许使用DELETE。级别:全局、数据库、表。


  • DROP 允许删除数据库、表和视图。级别:全局、数据库、表。


  • DROP ROLE 允许删除角色。级别:全局。


  • EVENT 允许使用事件调度器的事件。级别:全局、数据库。


  • EXECUTE 允许执行存储过程。级别:全局、数据库、例程。


  • FILE 允许用户读取或写入文件。级别:全局。


  • GRANT OPTION 允许将权限授予或从其他账户中移除。级别:全局、数据库、表、例程、代理。


  • INDEX 允许创建或删除索引。级别:全局、数据库、表。


  • INSERT 允许使用INSERT。级别:全局、数据库、表、列。


  • LOCK TABLES 允许在具有SELECT权限的表上使用LOCK TABLES。级别:全局、数据库。


  • 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 TO、CHANGE MASTER TO、KILL、PURGE BINARY LOGS、SET GLOBAL和mysqladmin debug命令。级别:全局。


  • TRIGGER 允许触发器操作。级别:全局、数据库、表。


  • UPDATE 允许使用UPDATE。级别:全局、数据库、表、列。


  • USAGE "无权限" 的同义词。


动态权限

  • 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 Cluster)之间共享用户或角色。级别:全局。


  • 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 启用设置非自身调用者值。级别:全局。


  • SHOW_ROUTINE 启用访问存储过程定义。级别:全局。


  • SKIP_QUERY_REWRITE 不重写此用户执行的查询。级别:全局。


  • SYSTEM_USER 将帐户指定为系统帐户。级别:全局。


  • SYSTEM_VARIABLES_ADMIN 启用修改或持久化全局系统变量。级别:全局。


  • TABLE_ENCRYPTION_ADMIN 启用覆盖默认加密设置。级别:全局。


  • TP_CONNECTION_ADMIN 启用线程池连接管理。级别:全局。


  • VERSION_TOKEN_ADMIN 启用版本令牌函数的使用。级别:全局。


  • XA_RECOVER_ADMIN 启用XA RECOVER执行。级别:全局。


触发器与表相关联。要创建或删除触发器,必须具有表的TRIGGER权限,而不是触发器本身的权限。


在GRANT语句中,ALL [PRIVILEGES]或PROXY权限必须单独命名,并且不能与其他权限一起指定。ALL [PRIVILEGES]表示在授予权限的级别上可用的所有权限,但不包括GRANT OPTION和PROXY权限。


MySQL账户信息存储在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 OPTION或PROXY权限。


如果存在object_type子句,则应在表、存储函数或存储过程为下一个对象时将其指定为TABLE、FUNCTION或PROCEDURE。


用户对数据库、表、列或例程拥有的权限是逻辑OR运算得到的账户权限在每个权限级别上的结果,包括全局级别。不能通过在较低级别缺少该权限来否决在较高级别授予的权限。例如,以下语句在全局范围内授予SELECT和INSERT权限:

GRANT SELECT, INSERT ON *.* TO u1;


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


从MySQL 8.0.16版本开始,如果启用了partial_revokes系统变量,可以显式地否定在全局级别授予的权限,并撤销它们用于特定数据库:

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


前述语句的结果是SELECT对所有表应用全局范围,而INSERT和UPDATE除了db1中的表之外都应用全局范围。对db1的帐户访问是只读的。


如果您为任何用户使用表、列或例程权限,服务器将检查所有用户的表、列和例程权限,这会稍微减慢MySQL的速度。同样地,如果您限制了任何用户的查询、更新或连接数目,服务器必须监视这些值。


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


重要提示:
当您删除数据库或表时,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 *.*),那么权限将分配给默认数据库的数据库级别。如果没有默认数据库,则会发生错误。


CREATE、DROP、EVENT、GRANT OPTION、LOCK TABLES和REFERENCES权限可以在数据库级别指定。表或例程的权限也可以在数据库级别指定,在这种情况下,它们适用于数据库中的所有表或例程。


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创建的表,即使表名相同也是如此。


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


列权限

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

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


在对列(即使用column_list子句时)使用时,可允许的priv_type值为INSERT、REFERENCES、SELECT和UPDATE。


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


存储过程权限

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


代理用户权限

PROXY权限使一个用户可以成为另一个用户的代理。代理用户冒充或承担被代理用户的身份,即获取被代理用户的权限。

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


当授予PROXY权限时,GRANT语句中只能命名这一权限,并且唯一允许的WITH选项是WITH GRANT OPTION。


代理需要通过一个插件进行身份验证,该插件在代理用户连接时将被代理用户的名称返回给服务器,并且代理用户必须具有被代理用户的PROXY权限。


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


授予权限

没有ON子句的GRANT语法授予的是角色而不是个别权限。角色是一组命名的权限集合。例如:

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


每个要授予的角色必须存在,并且每个要授予的用户帐户或角色也必须存在。从MySQL 8.0.16版本开始,不能将角色授予匿名用户。


授予角色不会自动使角色生效。


授予这些角色所需的权限如下:


  • 如果你拥有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子句和权限限制

从MySQL 8.0.16开始,GRANT命令具有一个AS user [WITH ROLE]子句,用于指定用于语句执行的权限上下文的附加信息。尽管该语法在SQL级别可见,但其主要目的是允许通过在二进制日志中显示这些由部分撤销导致的授权限制,从而在所有节点上实现统一的复制。


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


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


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


  • 如果给出了WITH ROLE选项,则必须授予指定用户的所有角色。


  • 指定的用户应为以'user_name'@'host_name'、CURRENT_USER或CURRENT_USER()指定的MySQL帐户。当前用户可以与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;


还要创建一个解除某些权限限制并将该角色授予u1的角色r1:

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`@`%`         |
+----------------------------------------------------+


如前所述,GRANT语句中的AS子句只能添加权限限制,不能提升权限。因此,尽管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权限,则该用户可以授予INSERT、SELECT和UPDATE权限。


对于非管理用户,不应该全局或为mysql系统模式授予ALTER权限。如果这样做,用户可以尝试通过重命名表来破坏权限系统!


MySQL和标准SQL版本的GRANT命令

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


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


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


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


  • 标准SQL的权限以层次结构方式进行构建。如果您删除一个用户,该用户被授予的全部权限都将被撤销。在使用DROP USER的情况下,MySQL也是如此。


  • 在标准SQL中,当您删除一张表时,所有与该表相关的权限都会被撤销。在标准SQL中,当您撤销一项权限时,所有基于该权限授予的权限也会被撤销。在MySQL中,可以使用DROP USER或REVOKE语句撤销权限。


  • 在MySQL中,可以只对表中的某些列拥有INSERT权限。在这种情况下,只要您仅为具有INSERT权限的列插入值,就可以执行INSERT语句。如果严格SQL模式未启用,则省略的列将设置为其隐含的默认值。在严格模式下,如果任何省略的列没有默认值,则拒绝该语句。(标准SQL要求您对所有列都具有INSERT权限。)