MySQL8 中文参考(六十四)(mysql8.025)

MySQL8 中文参考(六十四) 原文:docs.oracle.com/javase/tutorial/reallybigindex.html 原文:dev.mysql.com/doc/refman/8.0/en

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

原文:dev.mysql.com/doc/refman/8.0/en/diagnostics-area.html

15.6.7.7 MySQL 诊断区

SQL 语句生成输入到诊断区域的诊断信息。标准SQL 有一堆诊断区域,每个嵌套执行上下文都有一个诊断区域。标准SQL 还支持GET STACKED DIAGNOSTICS 语法,用于在条件处理程序执行期间引用第二个诊断区域。

下面的讨论描述了MySQL诊断区的结构、MySQL识别的信息项、语句如何清除和设置诊断区以及如何将诊断区压入堆栈和从堆栈中弹出。

诊断区域配置

诊断区域信息项

如何清除和填充诊断区域

诊断区域堆栈的工作原理

与诊断区域相关的系统变量

诊断区结构

诊断区域包含两类信息:

语句信息,例如提出的条件数和受影响的行数。

状态信息,例如错误代码和消息。如果语句中出现多个条件,则这部分诊断区域对于每个条件区域都有一个条件区域。如果该语句没有生成条件,则这部分诊断区域为空。

对于生成三个条件的语句,诊断区域包含以下语句和条件信息:

详细信息:

行数

.其他声明信息项.

条件区域列表:

条件区1:

条件1 的错误代码

条件1 的错误消息

.其他状态信息项.

条件区2:

条件2: 的错误代码

情况2 错误消息

.其他状态信息项.

条件区3:

情况3 错误代码

情况3 错误消息

.其他状态信息项.

诊断区信息项

诊断区域包含语句和条件的信息项。数字项是整数。字符项的字符集是UTF-8。所有项目都不能为NULL。如果您在诊断区域中设置的语句或条件项不是由语句设置的,则其值为0 或空字符串,具体取决于该项的数据类型。

诊断区的语句信息部分包括:

NUMBER: 一个整数,表示包含信息的条件区域的数量。

ROW_COUNT: 一个整数,指示受该语句影响的行数。 ROW_COUNT 与ROW_COUNT() 函数具有相同的值(请参见第14.15 节“信息函数”)。

诊断区域的条件信息部分包含每个条件的条件区域。条件区的范围是1到NUMBER,即语句条件项的值编号。如果NUMBER 为0,则没有条件区域。

每个标准区域包含以下列表中的项目:除了MYSQL_ERRNO(它是MySQL 的扩展)之外,所有项目都是标准SQL。这些定义适用于非信号条件(即由SIGNAL 或RESIGNAL 语句生成的条件)。对于无信号条件,MySQL只设置不描述信号对条件区域影响的条件项。我稍后会解释。

CLASS_ORIGIN:包含RETURNED_SQLSTATE 值的类的字符串。如果RETURNED_SQLSTATE 值以SQL 标准文档ISO 9075-2(第24.1 节,SQLSTATE)中定义的类值开头,则CLASS_ORIGIN 将为“ISO 9075”。否则,CLASS_ORIGIN 为“MySQL”。

SUBCLASS_ORIGIN:包含RETURNED_SQLSTATE 值的子类的字符串。如果CLASS_ORIGIN 为“ISO 9075”或RETURNED_SQLSTATE 以“000”结尾,则SUBCLASS_ORIGIN 为“ISO 9075”。否则,SUBCLASS_ORIGIN 为“MySQL”。

RETURNED_SQLSTATE:指示条件的SQLSTATE 值的字符串。

MESSAGE_TEXT:指示条件错误消息的字符串。

MYSQL_ERRNO:一个整数,指示该条件的MySQL 错误代码。

CONSTRAINT_CATALOG、CONSTRAINT_SCHEMA、CONSTRAINT_NAME:指示约束冲突的目录、模式和名称的字符串。它们总是空的。

CATALOG_NAME、SCHEMA_NAME、TABLE_NAME、COLUMN_NAME:标识与条件关联的目录、架构、表和列的字符串。它们总是空的。

CURSOR_NAME:指示光标名称的字符串。这个地方永远是空的。

有关特定错误RETURNED_SQLSTATE、MESSAGE_TEXT 和MYSQL_ERRNO 值,请参阅服务器错误消息参考。

如果SIGNAL(或RESIGNAL)语句满足诊断区域,则其SET 子句可以将有效的数据类型值分配给除RETURNED_SQLSTATE 之外的任何条件信息项。 SIGNAL 还设置RETURNED_SQLSTATE 值,但它不会直接在SET 子句中设置它。该值是从SIGNAL 语句的SQLSTATE 参数获取的。

SIGNAL 还设置语句信息项。将数字设置为1。出错时将ROW_COUNT 设置为-1,否则设置为0。

诊断区域如何清除和填充

非诊断SQL 语句会自动放置在诊断区域中,并且可以使用SIGNAL 和RESIGNAL 语句显式设置其内容。您可以通过使用GET DIAGNOSTICS 提取特定项目来检查诊断区域,也可以使用SHOW WARNINGS 或SHOW ERRORS 查看状况和错误。

SQL语句清除和设置诊断区域如下:

当服务器开始执行解析的语句时,它会清除非诊断语句的诊断区域。诊断语句不会清除诊断区域。这些陈述仅用于诊断目的。

接受诊断

显示错误

显示警告

如果某个语句导致某个条件,则属于前一个语句的条件将从诊断区域中清除。唯一的例外是GET DIAGNOSTICS 和RESIGNAL 引发的条件将添加到诊断区域而不清除它。

因此,即使在语句开始执行时诊断区域通常不会被清除,但在语句生成条件时它也会被清除。

以下示例使用SHOW WARNINGS 显示存储在诊断区域中的条件信息,并显示各种语句对诊断区域的影响。

此DROP TABLE 语句会清除诊断区域并在出现情况时填充它。

mysql 如果存在则删除表test.no_such_table;

查询正常,0 行受影响,1 条警告(0.01 秒)

显示mysql 警告;

+——+——+———————————— — –+

| 级别代码|

+——+——+———————————— — –+

| 注意| 未知表“test.no_such_table”

+——+——+———————————— — –+

一组1 行(0.00 秒)

该SET 语句会生成错误,因此请清除并填充诊断区域。

mysql SET @x=@@x;

错误1193 (HY000): 未知的系统变量“x”

显示mysql 警告;

+——+——+————————+

| 级别代码|

+——+——+————————+

| 错误| 未知的系统变量“x”

+——+——+————————+

一组1 行(0.00 秒)

前面的SET 语句生成了一个条件,因此此时唯一有效的GET DIAGNOSTICS 条件编号为1。以下语句使用条件号2 生成警告,该警告添加到诊断区域而不清除它。

获取mysql 诊断条件2 @p=MESSAGE_TEXT;

查询正常,0 行受影响,1 条警告(0.00 秒)

显示mysql 警告;

+——+——+———————————— — +

| 级别代码|

+——+——+———————————— — +

| 错误| 未知的系统变量“xx”

| 错误| 条件编号无效

+——+——+———————————— — +

2 行组(0.00 秒)

相同的GET DIAGNOSTICS 语句成功运行,因为诊断区域中有两个条件。

获取mysql 诊断条件2 @p=MESSAGE_TEXT;

查询正常,0 行受影响(0.00 秒)

mysql 选择@p;

+————————————————+

| @p |

+————————————————+

| 条件编号无效。

+————————————————+

一组1 行(0.01 秒)

诊断区域栈的工作原理

当发生压入诊断区域堆栈时,第一个(当前)诊断区域成为第二个(堆栈)诊断区域,并且新的当前诊断区域将创建为其副本。在以下情况下,诊断区域会被压入堆栈并从堆栈中弹出:

运行保存的程序

推送发生在程序运行之前,弹出发生在程序运行之后。如果存储过程在处理程序运行时退出,则可能会弹出多个诊断区域。这是由于没有合适的处理程序的异常或处理程序内的返回引起的。

诊断区域中弹出的任何警告或错误条件都将添加到当前诊断区域,但在触发器的情况下只会添加错误。当存储过程退出时,调用者在当前诊断区域中检查这些状态。

在存储过程中执行条件处理程序

如果压入是由于条件处理程序的激活而发生的,则堆栈诊断区域是压入之前存储程序中的当前区域。新的当前诊断区域成为处理程序的当前诊断区域。获取[当前]诊断和获取堆栈诊断可以在处理程序中使用,以访问当前(处理程序)和堆栈(存储的程序)诊断区域的内容。最初返回相同的结果,但处理程序内执行的语句修改当前诊断区域,根据通常的规则清除和设置其内容(请参阅“如何清除和设置诊断区域”)。堆栈诊断区域不能通过处理程序内执行的语句进行修改,除非使用reissue。

当处理程序执行成功时,当前(处理程序)诊断区域被弹出,并且堆栈(存储程序)诊断区域再次成为当前诊断区域。在处理程序执行期间添加到处理程序诊断区域的条件将添加到当前诊断区域。

补发

reissue 语句传递可在存储过程的内部复合语句内的条件处理程序执行期间使用的错误条件信息。重新发布按照第15.6.7.4 节“重新发布声明”中描述的方式修改诊断堆栈,并且可能会在交付之前更改部分或全部信息。

与诊断区相关的系统变量

某些系统变量控制或与诊断区域的特定方面相关。

max_error_count 控制诊断区域内条件区域的数量。如果发生的条件超过此数量,MySQL 会默默地丢弃有关其他条件的信息。 (总是添加通过RESIGNAL 添加的条件,并根据需要丢弃旧条件以腾出空间。)

warning_count 表示发生的情况的数量。这包括错误、警告和评论。通常NUMBER 和warning_count 是相同的。但是,如果生成的条件数量超过max_error_count,则warning_count 的值会继续增加,但诊断区域不会存储额外的条件,因此NUMBER 仍限制为max_error_count。

error_count 表示发生的错误数。该值包括“未找到”和异常情况,但不包括警告和注释。与warning_count 一样,其值可以超过max_error_count。

如果sql_notes 系统变量设置为0,则不会保存任何注释,并且warning_count 不会增加。

示例:如果max_error_count 为10,则诊断区域最多可包含10 个条件区域。假设一个语句有20 个条件,其中12 个是错误。在本例中,诊断区域包含前10 个条件:NUMBER 为10、warning_count 为20、error_count 为12。

对max_error_count 的更改只有在下次尝试更改诊断区域时才会生效。如果诊断区域包含10 个条件区域并且max_error_count 设置为5,则这不会立即影响诊断区域的大小或内容。

原文:dev.mysql.com/doc/refman/8.0/en/conditions-and-parameters.html

15.6.7.8 条件处理和 OUT 或 INOUT 参数

如果存储过程因未处理的异常而退出,则OUT 和INOUT 参数的更改值不会传播到调用方。

当包含RESIGNAL 语句的CONTINUE 或EXIT 处理程序处理异常时,执行RESIGNAL 语句会弹出诊断区域堆栈,该堆栈会发出异常信号(即,在进入处理程序之前存在的信息)。如果异常是错误,则OUT 和INOUT 参数的值不会传播到调用者。

15.6.8 条件处理的限制

原文:dev.mysql.com/doc/refman/8.0/en/condition-handling-restrictions.html

SIGNAL、RESIGNAL 和GET DIAGNOSTICS 不能用作准备语句。例如,以下语句无效:

从\’SIGNAL SQLSTATE \’02000\’\’ 准备stmt1;

类\’04\’的SQLSTATE值没有被特殊处理。这些异常的处理方式与任何其他异常一样。

在标准SQL 中,第一个条件与前一个SQL 语句返回的SQLSTATE 值相关。 MySQL 不保证这一点,因此您无法执行以下操作来获取主要错误:

获取诊断条件1 @errno=MYSQL_ERRNO;

相反,请执行以下操作:

获取诊断@cno=NUMBER;

获取诊断条件@cno @errno=MYSQL_ERRNO;

15.7 数据库管理语句

原文:dev.mysql.com/doc/refman/8.0/en/sql-server-administration-statements.html

15.7.1 账户管理声明

15.7.2 资源组管理语句

15.7.3 表维护语句

15.7.4 组件、插件和可加载函数语句

15.7.5 克隆语句

15.7.6 SET语句

15.7.7 SHOW语句

15.7.8 其他管理报表

15.7.1 账户管理语句

原文:dev.mysql.com/doc/refman/8.0/en/account-management-statements.html

15.7.1.1 修改用户语句

15.7.1.2 创建角色语句

15.7.1.3 创建用户语句

15.7.1.4 删除角色语句

15.7.1.5 删除用户语句

15.7.1.6 授权声明

15.7.1.7 重命名用户语句

15.7.1.8 撤消语句

15.7.1.9 设置默认角色语句

15.7.1.10 密码设置语句

15.7.1.11 角色配置语句

MySQL 帐户信息存储在mysql 系统架构的表中。该数据库和访问控制系统在第7 章“MySQL 服务器管理”中详细解释。请参阅本章了解更多信息。

重要的

某些MySQL 版本会对授权表进行更改以添加新的权限和功能。为了确保您可以利用新功能,请在每次升级MySQL 时将授权表更新为当前结构。请参阅第3 章“升级MySQL”。

如果启用了read_only 系统变量,除了其他所需的权限之外,帐户管理语句还需要CONNECTION_ADMIN 权限(或已弃用的SUPER 权限)。这是因为它修改了mysql 系统模式中的表。

帐户管理语句是原子的并且是安全的。有关更多信息,请参阅原子数据定义语句支持。

原文:dev.mysql.com/doc/refman/8.0/en/alter-user.html

15.7.1.1 ALTER USER Statement

更改用户[如果可用]

*用户* [*身份验证选项*] [, *用户* [*身份验证选项*]] .

[要求{无| *tls_option* [[AND] *tls_option*] .}]

[带有*资源选项* [*资源选项*] .]

[*密码选项* *锁定选项*].

[注释\’*注释字符串*\’ | 属性\’*json_object*\’]

更改用户[如果可用]

USER() *user_func_auth_option*

更改用户[如果可用]

*用户* [*注册选项*]

更改用户[如果可用]

USER() [*注册选项*]

更改用户[如果可用]

*用户* 默认角色

{无| 全部| *角色* [,*角色* ] .}

*用户*:

(请参阅第8.2.4 节“指定帐户名称”)

*身份验证选项*: {

由“*auth_string*”标识

[替换\’*current_auth_string*\’]

[保留当前密码]

| 通过随机密码识别

[替换\’*current_auth_string*\’]

[保留当前密码]

| 由*auth_plugin* 识别

| 在*auth_plugin* 中由\’*auth_string*\’ 识别

[替换\’*current_auth_string*\’]

[保留当前密码]

| 由*auth_plugin* 通过随机密码识别

[替换\’*current_auth_string*\’]

[保留当前密码]

| *auth_plugin* 标识为“*auth_string*”

| 放弃旧密码

| 添加*因素* *因素验证选项* [添加*因素* *因素验证选项*]

| 修改*factor* *factor_auth_option* [修改*factor* *factor_auth_option*]

| 下降*系数* [下降*系数*]

}

*user_func_auth_option*: {

由“*auth_string*”标识

[替换\’*current_auth_string*\’]

[保留当前密码]

| 放弃旧密码

}

*factor_auth_option*: {

由“*auth_string*”标识

| 通过随机密码识别

| 在*auth_plugin* 中由\’*auth_string*\’ 识别

| 由*auth_plugin* 通过随机密码识别

| *auth_plugin* 标识为“*auth_string*”

}

*注册选项*: {

*元素* 开始注册

| *factor* 结束注册将CHALLENGE_RESPONSE 设置为\’*auth_string*\’

| *元素* 取消注册

}

*系数*: {2 | 3}

*tls_选项*: {

SSL协议

|X509

| 密码“*密码*”

| 出版商“*出版商*”

| 主题“*主题*”

}

*资源选项*: {

MAX_QUERIES_PER_HOUR *数量*

| 每小时最多更新数*计数*

| 每小时最多连接数*数量*

| 最大用户连接数*c

ount*
}
*password_option*: {
PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL *N* DAY]
| PASSWORD HISTORY {DEFAULT | *N*}
| PASSWORD REUSE INTERVAL {DEFAULT | *N* DAY}
| PASSWORD REQUIRE CURRENT [DEFAULT | OPTIONAL]
| FAILED_LOGIN_ATTEMPTS *N*
| PASSWORD_LOCK_TIME {*N* | UNBOUNDED}
}
*lock_option*: {
ACCOUNT LOCK
| ACCOUNT UNLOCK
}

ALTER USER语句修改 MySQL 账户。它允许对现有账户进行身份验证、角色、SSL/TLS、资源限制、密码管理、注释和属性属性的修改。它还可以用于锁定和解锁账户。

在大多数情况下,ALTER USER需要全局CREATE USER权限,或者mysql系统模式的UPDATE权限。例外情况包括:

任何使用非匿名账户连接到服务器的客户端都可以更改该账户的密码。(特别是,您可以更改自己的密码。)要查看服务器对您进行身份验证的账户,请调用CURRENT_USER()函数:
SELECT CURRENT_USER();
对于DEFAULT ROLE语法,ALTER USER需要这些权限:

为另一个用户设置默认角色需要全局CREATE USER权限,或者mysql.default_roles系统表的UPDATE权限。
为自己设置默认角色不需要特殊权限,只要您想要的默认角色已经授予您。
修改次要密码的语句需要这些权限:

使用RETAIN CURRENT PASSWORD或DISCARD OLD PASSWORD子句需要APPLICATION_PASSWORD_ADMIN权限,用于适用于您自己账户的ALTER USER语句。该权限用于操作您自己的次要密码,因为大多数用户只需要一个密码。
如果要允许一个账户操作所有账户的次要密码,则需要CREATE USER权限,而不是APPLICATION_PASSWORD_ADMIN。

当启用read_only系统变量时,ALTER USER还需要CONNECTION_ADMIN权限(或已弃用的SUPER权限)。

从 MySQL 8.0.27 开始,这些额外的权限考虑因素适用:

authentication_policy系统变量对ALTER USER语句中与身份验证相关的子句的使用施加了一定的约束;有关详细信息,请参阅该变量的描述。如果具有AUTHENTICATION_POLICY_ADMIN权限,则不适用这些约束。
要修改使用无密码身份验证的帐户,必须具有PASSWORDLESS_USER_ADMIN权限。

默认情况下,如果尝试修改不存在的用户,则会发生错误。如果提供了IF EXISTS子句,则该语句会对每个不存在的命名用户产生警告,而不是错误。

重要提示

在某些情况下,ALTER USER可能会记录在服务器日志中或客户端的历史文件中,例如~/.mysql_history,这意味着明文密码可能会被任何具有读取权限的人读取。有关服务器日志中发生这种情况的条件以及如何控制它的信息,请参阅第 8.1.2.3 节,“密码和日志记录”。有关客户端日志记录的类似信息,请参阅第 6.5.1.3 节,“mysql 客户端日志记录”。

ALTER USER语句有几个方面,分别在以下主题下描述:

修改用户概述
修改用户身份验证选项
修改用户多因素身份验证选项
修改用户注册选项
修改用户角色选项
修改用户 SSL/TLS 选项
修改用户资源限制选项
修改用户密码管理选项
修改用户注释和属性选项
修改用户账户锁定选项
修改用户二进制日志记录

修改用户概述

对于每个受影响的帐户,ALTER USER修改mysql.user系统表中对应行,以反映语句中指定的属性。未指定的属性保留其当前值。

每个帐户名称使用第 8.2.4 节“指定帐户名称”中描述的格式。如果省略帐户名称的主机名部分,默认为\’%\’。还可以指定CURRENT_USER或CURRENT_USER()来引用与当前会话关联的帐户。

仅在一个情况下,可以使用USER()函数指定帐户:

ALTER USER USER() IDENTIFIED BY \’*auth_string*\’;

这种语法使您可以在不明确命名您的帐户的情况下更改自己的密码。(该语法还支持 ALTER USER 身份验证选项中描述的REPLACE、RETAIN CURRENT PASSWORD和DISCARD OLD PASSWORD子句。)

对于允许*auth_option值跟随user值的ALTER USER语法,auth_option通过指定帐户身份验证插件、凭据(例如密码)或两者来指示帐户如何进行身份验证。每个auth_option*值仅适用于紧随其前的帐户。

根据*user规范,该语句可能包括 SSL/TLS、资源限制、密码管理和锁定属性的选项。所有这些选项都是语句的全局选项,并适用于语句中命名的所有*帐户。

示例:更改帐户的密码并将其过期。结果是,用户必须使用指定的密码连接,并在下次连接时选择一个新密码:

ALTER USER \’jeffrey\’@\’localhost\’
IDENTIFIED BY \’*new_password*\’ PASSWORD EXPIRE;

示例:修改帐户以使用caching_sha2_password身份验证插件和给定密码。要求每 180 天选择一个新密码,并启用失败登录跟踪,以便连续三次输入错误密码导致临时锁定帐户两天:

ALTER USER \’jeffrey\’@\’localhost\’
IDENTIFIED WITH caching_sha2_password BY \’*new_password*\’
PASSWORD EXPIRE INTERVAL 180 DAY
FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 2;

示例:锁定或解锁帐户:

ALTER USER \’jeffrey\’@\’localhost\’ ACCOUNT LOCK;
ALTER USER \’jeffrey\’@\’localhost\’ ACCOUNT UNLOCK;

示例:要求帐户使用 SSL 连接,并在每小时建立 20 个连接的限制:

ALTER USER \’jeffrey\’@\’localhost\’
REQUIRE SSL WITH MAX_CONNECTIONS_PER_HOUR 20;

示例:更改多个帐户,指定一些每个帐户的属性和一些全局属性:

ALTER USER
\’jeffrey\’@\’localhost\’
IDENTIFIED BY \’*jeffrey_new_password*\’,
\’jeanne\’@\’localhost\’,
\’josh\’@\’localhost\’
IDENTIFIED BY \’*josh_new_password*\’
REPLACE \’*josh_current_password*\’
RETAIN CURRENT PASSWORD
REQUIRE SSL WITH MAX_USER_CONNECTIONS 2
PASSWORD HISTORY 5;

jeffrey后面的IDENTIFIED BY值仅适用于其紧接的帐户,因此它仅为jeffrey更改密码为\’*jeffrey_new_password*\’。对于jeanne,没有每个帐户的值(因此密码保持不变)。对于josh,IDENTIFIED BY建立了一个新密码(\’*josh_new_password*\’),指定REPLACE以验证发出ALTER USER语句的用户知道当前密码(\’*josh_current_password*\’),并且当前密码也保留为帐户的次要密码。(因此,josh可以使用主密码或次要密码连接。)

剩余属性全局适用于语句中命名的所有帐户,因此对于两个帐户:

连接需要使用 SSL。
该帐户最多可用于两个同时连接。
密码更改不能重复使用最近的五个密码。

示例:丢弃josh的次要密码,只留下主密码:

ALTER USER \’josh\’@\’localhost\’ DISCARD OLD PASSWORD;

在缺少特定类型选项的情况下,帐户在这方面保持不变。例如,没有锁定选项,帐户的锁定状态不会改变。

ALTER USER 认证选项

一个帐户名后面可以跟着一个*auth_option*认证选项,指定帐户认证插件、凭据,或两者兼有。它还可以包括一个密码验证子句,指定要替换的帐户当前密码,并管理帐户是否有次要密码。

注意

仅适用于使用将凭据存储在 MySQL 内部的认证插件的帐户的随机密码生成、密码验证和次要密码子句。对于使用针对 MySQL 外部凭据系统执行身份验证的插件的帐户,密码管理也必须在该系统外部处理。有关内部凭据存储的更多信息,请参见第 8.2.15 节,“密码管理”。

*auth_plugin*指定认证插件。插件名称可以是带引号的字符串文字,也可以是未带引号的名称。插件名称存储在mysql.user系统表的plugin列中。
对于不指定认证插件的*auth_option*语法,服务器分配默认插件,如默认认证插件中所述确定。有关每个插件的描述,请参见第 8.4.1 节,“认证插件”。
存储在内部的凭据存储在 mysql.user 系统表中。\’*auth_string*\’ 值或 RANDOM PASSWORD 指定账户凭据,分别作为明文(未加密)字符串或以与账户关联的认证插件期望的格式进行哈希处理的形式:

对于使用 BY \’*auth_string*\’ 语法的情况,该字符串是明文的,并且传递给认证插件进行可能的哈希处理。插件返回的结果存储在 mysql.user 表中。插件可以按照指定的值使用该值,这种情况下不会进行哈希处理。
对于使用 BY RANDOM PASSWORD 语法的情况,MySQL 生成一个随机密码并作为明文传递给认证插件进行可能的哈希处理。插件返回的结果存储在 mysql.user 表中。插件可以按照指定的值使用该值,这种情况下不会进行哈希处理。
随机生成的密码从 MySQL 8.0.18 开始可用,并具有 随机密码生成 中描述的特性。
对于使用 AS \’*auth_string*\’ 语法的情况,该字符串被假定已经是认证插件所需的格式,并且原样存储在 mysql.user 表中。如果插件需要哈希值,则该值必须已经以适合插件的格式进行哈希处理;否则,插件无法使用该值,也无法正确验证客户端连接。
从 MySQL 8.0.17 开始,哈希字符串可以是字符串文字或十六进制值。后者对应于当启用 print_identified_with_as_hex 系统变量时,包含不可打印字符的密码哈希的 SHOW CREATE USER 显示的值类型。
如果认证插件不对认证字符串进行哈希处理,则 BY \’*auth_string*\’ 和 AS \’*auth_string*\’ 子句具有相同的效果:认证字符串原样存储在 mysql.user 系统表中。
REPLACE \’*current_auth_string*\’ 子句执行密码验证,并从 MySQL 8.0.13 开始可用。如果给出:

REPLACE 指定要替换的账户当前密码,作为明文(未加密)字符串。
如果账户的密码更改需要指定当前密码以验证尝试进行更改的用户实际上知道当前密码,则必须给出该子句。
如果账户的密码更改可能但不一定需要指定当前密码,则该子句是可选的。
如果给出了该子句但与当前密码不匹配,则语句将失败,即使该子句是可选的。
只有在更改当前用户的账户密码时才能指定 REPLACE。
有关通过指定当前密码进行密码验证的更多信息,请参见第 8.2.15 节,“密码管理”。
RETAIN CURRENT PASSWORD和DISCARD OLD PASSWORD子句实现了双密码功能,并自 MySQL 8.0.14 起可用。两者都是可选的,但如果给出,则具有以下效果:

RETAIN CURRENT PASSWORD保留账户当前密码作为其次要密码,替换任何现有的次要密码。新密码成为主密码,但客户端可以使用账户使用主密码或次要密码连接到服务器。(例外情况:如果ALTER USER语句指定的新密码为空,则次要密码也变为空,即使给出了RETAIN CURRENT PASSWORD。)
如果为具有空主密码的账户指定了RETAIN CURRENT PASSWORD,则该语句将失败。
如果一个账户有次要密码,并且您更改其主密码而没有指定RETAIN CURRENT PASSWORD,则次要密码保持不变。
如果更改分配给账户的身份验证插件,则次要密码将被丢弃。如果更改身份验证插件并且还指定了RETAIN CURRENT PASSWORD,则该语句将失败。
DISCARD OLD PASSWORD丢弃次要密码(如果存在)。账户仅保留其主密码,客户端只能使用主密码连接到服务器。
有关双密码使用的更多信息,请参见第 8.2.15 节,“密码管理”。

ALTER USER允许这些*auth_option*语法:

IDENTIFIED BY \’*auth_string*\’ [REPLACE \’*current_auth_string*\’] [RETAIN CURRENT PASSWORD]
将账户身份验证插件设置为默认插件,将明文\’*auth_string*\’值传递给插件进行可能的哈希处理,并将结果存储在mysql.user系统表中的账户行中。
如果指定了REPLACE子句,则指定了当前账户密码,如本节前文所述。
如果给出了RETAIN CURRENT PASSWORD子句,则导致保留账户当前密码作为其次要密码,如本节前文所述。
IDENTIFIED BY RANDOM PASSWORD [REPLACE \’*current_auth_string*\’] [RETAIN CURRENT PASSWORD]
将账户认证插件设置为默认插件,生成一个随机密码,将明文密码值传递给插件进行可能的哈希处理,并将结果存储在mysql.user系统表中的账户行中。该语句还会将明文密码作为结果集返回,以便用户或应用程序执行该语句时使用。有关结果集和随机生成密码特性的详细信息,请参见随机密码生成。
REPLACE子句,如果给定,指定账户当前密码,如本节前文所述。
RETAIN CURRENT PASSWORD子句,如果给定,会导致账户当前密码保留为其次要密码,如本节前文所述。
IDENTIFIED WITH *auth_plugin*
将账户认证插件设置为*auth_plugin*,将凭据清空为空字符串(凭据与旧认证插件相关联,而不是新的插件),并将结果存储在mysql.user系统表中的账户行中。
此外,密码被标记为过期。用户在下次连接时必须选择新密码。
IDENTIFIED WITH *auth_plugin* BY \’*auth_string*\’ [REPLACE \’*current_auth_string*\’] [RETAIN CURRENT PASSWORD]
将账户认证插件设置为*auth_plugin*,将明文\’*auth_string*\’值传递给插件进行可能的哈希处理,并将结果存储在mysql.user系统表中的账户行中。
REPLACE子句,如果给定,指定账户当前密码,如本节前文所述。
RETAIN CURRENT PASSWORD子句,如果给定,会导致账户当前密码保留为其次要密码,如本节前文所述。
IDENTIFIED WITH *auth_plugin* BY RANDOM PASSWORD [REPLACE \’*current_auth_string*\’] [RETAIN CURRENT PASSWORD]
将账户认证插件设置为*auth_plugin*,生成一个随机密码,将明文密码值传递给插件进行可能的哈希处理,并将结果存储在mysql.user系统表中的账户行中。该语句还会将明文密码作为结果集返回,以便用户或应用程序执行该语句时使用。有关结果集和随机生成密码特性的详细信息,请参见随机密码生成。
REPLACE子句,如果给定,指定账户当前密码,如本节前文所述。
RETAIN CURRENT PASSWORD子句,如果给定,会导致账户当前密码保留为其次要密码,如本节前文所述。
IDENTIFIED WITH *auth_plugin* AS \’*auth_string*\’
将账户认证插件设置为*auth_plugin*,并将\’*auth_string*\’值原样存储在mysql.user账户行中。如果插件需要哈希字符串,则假定字符串已经以插件所需的格式进行了哈希处理。
DISCARD OLD PASSWORD
丢弃账户的次要密码,如果存在的话,如本节前面描述的。

示例:将密码指定为明文;使用默认插件:

ALTER USER \’jeffrey\’@\’localhost\’
IDENTIFIED BY \’*password*\’;

示例:指定认证插件,以及一个明文密码值:

ALTER USER \’jeffrey\’@\’localhost\’
IDENTIFIED WITH mysql_native_password
BY \’*password*\’;

示例:与前面的示例类似,但另外指定当前密码作为明文值,以满足用户更改时需要知道该密码的任何账户要求:

ALTER USER \’jeffrey\’@\’localhost\’
IDENTIFIED WITH mysql_native_password
BY \’*password*\’
REPLACE \’*current_password*\’;

除非当前用户是jeffrey,否则上述语句将失败,因为REPLACE仅允许更改当前用户的密码。

示例:建立一个新的主密码,并保留现有密码作为次要密码:

ALTER USER \’jeffrey\’@\’localhost\’
IDENTIFIED BY \’*new_password*\’
RETAIN CURRENT PASSWORD;

示例:丢弃次要密码,仅保留账户的主密码:

ALTER USER \’jeffery\’@\’localhost\’ DISCARD OLD PASSWORD;

示例:指定认证插件,以及一个哈希密码值:

ALTER USER \’jeffrey\’@\’localhost\’
IDENTIFIED WITH mysql_native_password
AS \’*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4\’;

有关设置密码和认证插件的更多信息,请参见第 8.2.14 节,“分配账户密码”和第 8.2.17 节,“可插拔认证”。

更改用户多因素认证选项

截至 MySQL 8.0.27,ALTER USER具有ADD、MODIFY和DROP子句,允许添加、修改或删除认证因素。在每种情况下,子句指定要对一个认证因素执行的操作,以及可选地对另一个认证因素执行的操作。对于每个操作,*factor*项指定了FACTOR关键字,前面跟着数字 2 或 3,以指示操作是应用于第二个还是第三个认证因素。(在此上下文中不允许使用 1。要对第一个认证因素执行操作,请使用 ALTER USER Authentication Options 中描述的语法。)

ALTER USER多因素认证子句的约束由authentication_policy系统变量定义。例如,authentication_policy设置控制账户可以拥有的认证因素数量,以及对于每个因素,允许使用哪些认证方法。请参阅配置多因素认证策略。

当ALTER USER在单个语句中添加、修改或删除第二个和第三个因素时,操作是按顺序执行的,但如果序列中的任何操作失败,则整个ALTER USER语句将失败。

对于ADD,每个命名因素都不得已存在,否则无法添加。对于MODIFY和DROP,每个命名因素必须存在才能被修改或删除。如果定义了第二个和第三个因素,删除第二个因素会导致第三个因素取代它成为第二个因素。

此语句删除认证因素 2 和 3,从而将帐户从 3FA 转换为 1FA:

ALTER USER \’*user*\’ DROP 2 FACTOR 3 FACTOR;

有关其他ADD,MODIFY和DROP示例,请参阅开始使用多因素认证。

有关确定未命名插件的认证子句的默认认证插件的特定规则的信息,请参阅默认认证插件。

ALTER USER 注册选项

截至 MySQL 8.0.27,ALTER USER具有允许注册和注销 FIDO 设备的子句。有关更多信息,请参阅使用 FIDO 认证,FIDO 设备注销以及mysql客户端–fido-register-factor选项描述。

mysql客户端–fido-register-factor选项,用于 FIDO 设备注册,会导致mysql客户端生成并执行INITIATE REGISTRATION和FINISH REGISTRATION语句。这些语句不适用于手动执行。

ALTER USER 角色选项

ALTER USER … DEFAULT ROLE定义了用户连接到服务器并进行身份验证时激活的角色,或者用户在会话期间执行SET ROLE DEFAULT语句时激活的角色。

ALTER USER … DEFAULT ROLE 是 SET DEFAULT ROLE 的替代语法(参见 第 15.7.1.9 节,“SET DEFAULT ROLE Statement”)。然而,ALTER USER 只能为单个用户设置默认值,而 SET DEFAULT ROLE 可以为多个用户设置默认值。另一方面,您可以将 CURRENT_USER 指定为 ALTER USER 语句的用户名,而对于 SET DEFAULT ROLE 则不行。

每个用户账户名称使用先前描述的格式。

每个角色名称使用 第 8.2.5 节,“指定角色名称” 中描述的格式。例如:

ALTER USER \’joe\’@\’10.0.0.1\’ DEFAULT ROLE administrator, developer;

如果省略角色���称的主机名部分,则默认为 \’%\’。

在 DEFAULT ROLE 关键字后的子句允许这些值:

NONE:将默认设置为 NONE(无角色)。
ALL:将默认设置为授予该账户的所有角色。
*role* [, *role* ] …:将默认设置为指定的角色,这些角色必须在执行 ALTER USER … DEFAULT ROLE 时存在并授予该账户。

修改用户 SSL/TLS 选项

MySQL 可以检查 X.509 证书属性,除了基于用户名和凭据的常规身份验证外。有关在 MySQL 中使用 SSL/TLS 的背景信息,请参见 第 8.3 节,“使用加密连接”。

要为 MySQL 账户指定 SSL/TLS 相关选项,请使用包含一个或多个 tls_option 值的 REQUIRE 子句。

REQUIRE 选项的顺序无关紧要,但不能指定两次选项。在 REQUIRE 选项之间的 AND 关键字是可选的。

ALTER USER 允许这些 tls_option 值:

NONE
表明由该语句指定的所有账户没有 SSL 或 X.509 要求。如果用户名和密码有效,则允许非加密连接。如果客户端具有正确的证书和密钥文件,则客户端可以选择使用加密连接。
ALTER USER \’jeffrey\’@\’localhost\’ REQUIRE NONE;
客户端默认尝试建立安全连接。对于具有 REQUIRE NONE 的客户端,如果无法建立安全连接,则连接尝试会回退到非加密连接。要求加密连接,客户端只需指定 –ssl-mode=REQUIRED 选项;如果无法建立安全连接,则连接尝试失败。
SSL
告诉服务器只允许通过加密连接访问由该语句指定的所有账户。
ALTER USER \’jeffrey\’@\’localhost\’ REQUIRE SSL;
客户端默认尝试建立安全连接。对于具有REQUIRE SSL的帐户,如果无法建立安全连接,则连接尝试失败。
X509
对于所有由该语句命名的帐户,要求客户端提供有效证书,但确切的证书、颁发者和主题并不重要。唯一的要求是应该能够使用其中一个 CA 证书验证其签名。使用 X.509 证书始终意味着加密,因此在这种情况下SSL选项是不必要的。
ALTER USER \’jeffrey\’@\’localhost\’ REQUIRE X509;
对于具有REQUIRE X509的帐户,客户端必须指定–ssl-key和–ssl-cert选项进行连接。(建议但不是必须还指定–ssl-ca,以便验证服务器提供的公共证书。)对于ISSUER和SUBJECT也是如此,因为这些REQUIRE选项暗示了X509的要求。
颁发者 \’*issuer*\’
对于所有由该语句命名的帐户,要求客户端提供由 CA\’*issuer*\’颁发的有效 X.509 证书。如果客户端提供的证书有效但颁发者不同,服务器将拒绝连接。使用 X.509 证书始终意味着加密,因此在这种情况下SSL选项是不必要的。
ALTER USER \’jeffrey\’@\’localhost\’
REQUIRE ISSUER \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL/CN=CA/emailAddress=ca@example.com\’;
因为ISSUER暗示了X509的要求,客户端必须指定–ssl-key和–ssl-cert选项进行连接。(建议但不是必须还指定–ssl-ca,以便验证服务器提供的公共证书。)
主题 \’*subject*\’
对于所有由该语句命名的帐户,要求客户端提供包含主题*subject*的有效 X.509 证书。如果客户端提供的证书有效但主题不同,服务器将拒绝连接。使用 X.509 证书始终意味着加密,因此在这种情况下SSL选项是不必要的。
ALTER USER \’jeffrey\’@\’localhost\’
REQUIRE SUBJECT \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL demo client certificate/
CN=client/emailAddress=client@example.com\’;
MySQL 对\’*subject*\’值与证书中的值进行简单的字符串比较,因此大小写和组件顺序必须与证书中的完全相同。
因为SUBJECT暗示了X509的要求,客户端必须指定–ssl-key和–ssl-cert选项进行连接。(建议但不是必须还指定–ssl-ca,以便验证服务器提供的公共证书。)
密码 \’*cipher*\’
对于语句命名的所有帐户,需要特定的密码方法来加密连接。需要此选项以确保使用足够强度的密码和密钥长度的密码和密钥。如果使用旧算法和短加密密钥的算法,则加密可能较弱。
ALTER USER \’jeffrey\’@\’localhost\’
REQUIRE CIPHER \’EDH-RSA-DES-CBC3-SHA\’;

SUBJECT、ISSUER和CIPHER选项可以在REQUIRE子句中组合使用:

ALTER USER \’jeffrey\’@\’localhost\’
REQUIRE SUBJECT \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL demo client certificate/
CN=client/emailAddress=client@example.com\’
AND ISSUER \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL/CN=CA/emailAddress=ca@example.com\’
AND CIPHER \’EDH-RSA-DES-CBC3-SHA\’;

ALTER USER 资源限制选项

可以对帐户使用服务器资源的限制进行限制,如第 8.2.21 节“设置帐户资源限制”中所讨论的。为此,请使用指定一个或多个*resource_option*值的WITH子句。

WITH选项的顺序无关紧要,除非给定资源限制多次指定,否则最后一次实例优先。

ALTER USER允许使用以下*resource_option*值:

MAX_QUERIES_PER_HOUR *count*、MAX_UPDATES_PER_HOUR *count*、MAX_CONNECTIONS_PER_HOUR *count*
对于语句命名的所有帐户,这些选项限制了在任何给定的一小时内每个帐户对服务器执行多少查询、更新和连接。如果*count*为0(默认值),这意味着该帐户没有限制。
MAX_USER_CONNECTIONS *count*
对于语句命名的所有帐户,限制每个帐户对服务器的最大同时连接数。非零*count明确指定了帐户的限制。如果count*为0(默认值),服务器将根据max_user_connections系统变量的全局值确定帐户的同时连接数。如果max_user_connections也为零,则该帐户没有限制。

示例:

ALTER USER \’jeffrey\’@\’localhost\’
WITH MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;

ALTER USER 密码管理选项

ALTER USER支持几个*password_option*值用于密码管理:

密码过期选项:您可以手动使帐户密码过期并建立其密码过期策略。策略选项不会使密码过期。相反,它们确定服务器如何根据密码年龄自动使帐户密码过期,该年龄是从最近更改帐户密码的日期和时间评估的。
密码重用选项:您可以基于密码更改次数、经过的时间或两者限制密码重用。
密码验证必需选项:您可以指示更改帐户密码的尝试是否必须指定当前密码,以验证试图进行更改的用户实际上知道当前密码。
不正确密码的失败登录跟踪选项:您可以导致服务器跟踪失败的登录尝试,并临时锁定给出太多连续不正确密码的帐户。可配置失败次数和锁定时间。

本节描述了密码管理选项的语法。有关建立密码管理策略的信息,请参见第 8.2.15 节“密码管理”。

如果指定了给定类型的多个密码管理选项,则最后一个优先。例如,PASSWORD EXPIRE DEFAULT PASSWORD EXPIRE NEVER与PASSWORD EXPIRE NEVER相同。

注意

除了与失败登录跟踪相关的选项外,密码管理选项仅适用于使用将凭据存储在 MySQL 内部的身份验证插件的帐户。对于使用针对 MySQL 外部凭据系统执行身份验证的插件的帐户,密码管理也必须在该系统外部处理。有关内部凭据存储的更多信息,请参见第 8.2.15 节“密码管理”。

如果客户端的帐户密码已手动过期或密码年龄被认为大于其允许的生命周期,根据自动过期策略,客户端的密码已过期。在这种情况下,服务器要么断开客户端的连接,要么限制其允许的操作(请参见第 8.2.16 节“服务器处理过期密码”)。受限客户端执行的操作会导致错误,直到用户建立新的帐户密码。

注意

尽管可以通过将过期密码重置为当前值来“重置”过期密码,但作为良好政策的一部分,最好选择不同的密码。 DBA 可以通过建立适当的密码重用策略来强制执行不重用。请参见密码重用策略。

ALTER USER允许这些*password_option*值来控制密码过期:

PASSWORD EXPIRE
立即标记由语句命名的所有帐户的密码过期。
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE;
PASSWORD EXPIRE DEFAULT
将由语句命名的所有帐户设置为适用全局过期策略,由default_password_lifetime系统变量指定。
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE DEFAULT;
PASSWORD EXPIRE NEVER
此过期选项覆盖了语句命名的所有帐户的全局策略。对于每个帐户,它禁用密码过期,使密码永不过期。
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE NEVER;
PASSWORD EXPIRE INTERVAL *N* DAY
此过期选项覆盖了声明中所有命名的账户的全局策略。对于每个账户,它将密码寿命设置为*N*天。以下声明要求每 180 天更改一次密码:
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE INTERVAL 180 DAY;

ALTER USER 允许这些*password_option*值来控制基于所需最小密码更改次数的先前密码重用:

PASSWORD HISTORY DEFAULT
设置所有由声明命名的账户,以便全局关于密码历史长度的策略适用,以禁止在由password_history系统变量指定的更改次数之前重用密码。
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD HISTORY DEFAULT;
PASSWORD HISTORY *N*
此历史长度选项覆盖了声明中所有命名的账户的全局策略。对于每个账户,它将密码历史长度设置为*N个密码,以禁止重新使用最近选择的N*个密码中的任何一个。以下声明禁止重新使用之前的 6 个密码:
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD HISTORY 6;

ALTER USER 允许这些*password_option*值来控制基于经过的时间重新使用先前密码的情况:

PASSWORD REUSE INTERVAL DEFAULT
设置所有由账户命名的声明,以便全局关于经过时间的策略适用,以禁止重用比由password_reuse_interval系统变量指定的天数新的密码。
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD REUSE INTERVAL DEFAULT;
PASSWORD REUSE INTERVAL *N* DAY
此经过时间选项覆盖了声明中所有命名的账户的全局策略。对于每个账户,它将密码重用间隔设置为*N*天,以禁止重用比该天数新的密码。以下声明禁止密码在 360 天内重用:
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD REUSE INTERVAL 360 DAY;

ALTER USER 允许这些*password_option*值来控制是否尝试更改账户密码必须指定当前密码,以验证尝试进行更改的用户实际上知道当前密码:

PASSWORD REQUIRE CURRENT
此验证选项覆盖了声明中所有命名的账户的全局策略。对于每个账户,它要求密码更改必须指定当前密码。
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD REQUIRE CURRENT;
PASSWORD REQUIRE CURRENT OPTIONAL
此验证选项覆盖了声明中所有命名的账户的全局策略。对于每个账户,它不要求密码更改必须指定当前密码。(当前密码可以给出,但不是必须的。)
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD REQUIRE CURRENT OPTIONAL;
PASSWORD REQUIRE CURRENT DEFAULT
设置所有由账户命名的声明,以便全局关于密码验证的策略适用,如password_require_current系统变量所指定的那样。
ALTER USER \’jeffrey\’@\’localhost\’ PASSWORD REQUIRE CURRENT DEFAULT;

从 MySQL 8.0.19 开始,ALTER USER 允许使用以下 password_option 值来控制失败登录跟踪:

FAILED_LOGIN_ATTEMPTS *N*
是否跟踪指定错误密码的账户登录尝试。N 必须是从 0 到 32767 的数字。值为 0 禁用失败登录跟踪。大于 0 的值表示多少连续密码失败会导致临时账户锁定(如果 PASSWORD_LOCK_TIME 也非零)。
PASSWORD_LOCK_TIME {*N* | UNBOUNDED}
在太多连续登录尝试提供错误密码后锁定账户多长时间。N 必须是从 0 到 32767 的数字,或 UNBOUNDED。值为 0 禁用临时账户锁定。大于 0 的值表示锁定账户的天数。值为 UNBOUNDED 导致账户锁定持续时间无限;一旦锁定,账户将保持锁定状态直到解锁。有关解锁发生的条件,请参阅 Failed-Login Tracking and Temporary Account Locking。

要实现失败登录跟踪和临时锁定,一个账户的 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 选项都必须非零。以下语句修改一个账户,使其在连续四次密码失败后保持锁定两天:

ALTER USER \’jeffrey\’@\’localhost\’
FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 2;

修改用户评论和属性选项

MySQL 8.0.21 及更高版本支持用户评论和用户属性,如 Section 15.7.1.3, “CREATE USER Statement” 中所述。这些可以通过 ALTER USER 使用 COMMENT 和 ATTRIBUTE 选项进行修改。不能在同一 ALTER USER 语句中同时指定这两个选项;尝试这样做会导致语法错误。

用户评论和用户属性存储在信息模式 USER_ATTRIBUTES 表中作为 JSON 对象;用户评论存储为此表的 ATTRIBUTE 列中 comment 键的值,如后面的讨论所示。COMMENT 文本可以是任意带引号的文本,并替换任何现有用户评论。ATTRIBUTE 值必须是 JSON 对象的有效字符串表示。这与任何现有用户属性合并,就好像在现有用户属性和新用户属性上使用了 JSON_MERGE_PATCH() 函数;对于重新使用的任何键,新值会覆盖旧值,如下所示:

mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER=\’bill\’ AND HOST=\’localhost\’;
+——+———–+—————-+
| USER | HOST | ATTRIBUTE |
+——+———–+—————-+
| bill | localhost | {\”foo\”: \”bar\”} |
+——+———–+—————-+
1 row in set (0.11 sec)
mysql> ALTER USER \’bill\’@\’localhost\’ ATTRIBUTE \'{\”baz\”: \”faz\”, \”foo\”: \”moo\”}\’;
Query OK, 0 rows affected (0.22 sec)
mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER=\’bill\’ AND HOST=\’localhost\’;
+——+———–+——————————+
| USER | HOST | ATTRIBUTE |
+——+———–+——————————+
| bill | localhost | {\”baz\”: \”faz\”, \”foo\”: \”moo\”} |
+——+———–+——————————+
1 row in set (0.00 sec)

要从用户属性中删除键及其值,将键设置为 JSON null(必须小写且不带引号),如下所示:

mysql> ALTER USER \’bill\’@\’localhost\’ ATTRIBUTE \'{\”foo\”: null}\’;
Query OK, 0 rows affected (0.08 sec)
mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER=\’bill\’ AND HOST=\’localhost\’;
+——+———–+—————-+
| USER | HOST | ATTRIBUTE |
+——+———–+—————-+
| bill | localhost | {\”baz\”: \”faz\”} |
+——+———–+—————-+
1 row in set (0.00 sec)

要将现有用户的注释设置为空字符串,请使用ALTER USER … COMMENT \’\’。这将在USER_ATTRIBUTES表中留下一个空的comment值;要完全删除用户注释,请使用ALTER USER … ATTRIBUTE …,将列键的值设置为 JSON null(小写,不带引号)。下面是一系列 SQL 语句的示例:

mysql> ALTER USER \’bill\’@\’localhost\’ COMMENT \’Something about Bill\’;
Query OK, 0 rows affected (0.06 sec)
mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER=\’bill\’ AND HOST=\’localhost\’;
+——+———–+—————————————————+
| USER | HOST | ATTRIBUTE |
+——+———–+—————————————————+
| bill | localhost | {\”baz\”: \”faz\”, \”comment\”: \”Something about Bill\”} |
+——+———–+—————————————————+
1 row in set (0.00 sec)
mysql> ALTER USER \’bill\’@\’localhost\’ COMMENT \’\’;
Query OK, 0 rows affected (0.09 sec)
mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER=\’bill\’ AND HOST=\’localhost\’;
+——+———–+——————————-+
| USER | HOST | ATTRIBUTE |
+——+———–+——————————-+
| bill | localhost | {\”baz\”: \”faz\”, \”comment\”: \”\”} |
+——+———–+——————————-+
1 row in set (0.00 sec)
mysql> ALTER USER \’bill\’@\’localhost\’ ATTRIBUTE \'{\”comment\”: null}\’;
Query OK, 0 rows affected (0.07 sec)
mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER=\’bill\’ AND HOST=\’localhost\’;
+——+———–+—————-+
| USER | HOST | ATTRIBUTE |
+——+———–+—————-+
| bill | localhost | {\”baz\”: \”faz\”} |
+——+———–+—————-+
1 row in set (0.00 sec)

ALTER USER 帐户锁定选项

MySQL 支持使用ACCOUNT LOCK和ACCOUNT UNLOCK选项进行帐户锁定和解锁,这些选项指定帐户的锁定状态。有关更多讨论,请参阅第 8.2.20 节,“帐户锁定”。

如果指定了多个帐户锁定选项,则最后一个优先。

ALTER USER … ACCOUNT UNLOCK 解锁由语句指定的任何因登录失败次数过多而暂时锁定的帐户。请参阅第 8.2.15 节,“密码管理”。

ALTER USER 二进制日志记录

ALTER USER 如果成功,则写入二进制日志,但如果失败则不会;在这种情况下,将发生回滚,不会进行任何更改。写入二进制日志的语句包括所有命名用户。如果给出了IF EXISTS子句,则甚至包括那些不存在且未被更改的用户。

如果原始语句更改了用户的凭据,则写入二进制日志的语句指定了该用户的适用身份验证插件,��定如下:

如果原始语句中指定了插件的名称,则插件的名称。
否则,与用户帐户关联的插件(如果用户存在),或者默认身份验证插件(如果用户不存在)。(如果写入二进制日志的语句必须为用户指定特定的身份验证插件,请在原始语句中包含它。)

如果服务器为写入二进制日志的语句中的任何用户添加默认身份验证插件,则会向错误日志中写入警告,列出这些用户。

如果原始语句指定了FAILED_LOGIN_ATTEMPTS或PASSWORD_LOCK_TIME选项,则写入二进制日志的语句包括该选项。

具有支持多因素身份验证(MFA)的子句的ALTER USER语句被写入二进制日志,但不包括ALTER USER *user factor* INITIATE REGISTRATION语句。

ALTER USER *user factor* FINISH REGISTRATION SET CHALLENGE_RESPONSE AS \’*auth_string*\’ 语句被写入二进制日志为ALTER USER *user* MODIFY *factor* IDENTIFIED WITH authentication_fido AS *fido_hash_string*;
在复制环境中,复制用户需要PASSWORDLESS_USER_ADMIN权限来执行对使用authentication_fido插件配置为无密码身份验证的帐户进行ALTER USER … MODIFY操作。

原文:dev.mysql.com/doc/refman/8.0/en/create-role.html

15.7.1.2 CREATE ROLE Statement

CREATE ROLE [IF NOT EXISTS] *role* [, *role* ] …

CREATE ROLE 创建一个或多个角色,这些角色是命名的权限集合。要使用此语句,您必须具有全局CREATE ROLE或CREATE USER权限。当启用read_only系统变量时,CREATE ROLE 还需要CONNECTION_ADMIN权限(或已弃用的SUPER权限)。

创建角色时,角色被锁定,没有密码,并分配默认的身份验证插件。(这些角色属性可以由具有全局CREATE USER权限的用户稍后使用ALTER USER语句更改。)

CREATE ROLE 对所有命名角色要么成功,要么回滚并且不起作用,如果发生任何错误。默认情况下,如果尝试创建已经存在的角色,则会发生错误。如果给出了IF NOT EXISTS子句,则该语句对每个已经存在的命名角色产生警告,而不是错误。

如果成功,该语句将写入二进制日志,但如果失败则不会写入;在这种情况下,将发生回滚,不会进行任何更改。写入二进制日志的语句包括所有命名角色。如果给出了IF NOT EXISTS子句,则即使已经存在且未被创建的角色也会包括在内。

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

CREATE ROLE \’admin\’, \’developer\’;
CREATE ROLE \’webapp\’@\’localhost\’;

角色名称的主机名部分,如果省略,默认为\’%\’。

有关角色使用示例,请参见第 8.2.10 节,“使用角色”。

原文:dev.mysql.com/doc/refman/8.0/en/create-user.html

15.7.1.3 CREATE USER Statement

CREATE USER [IF NOT EXISTS]
*user* [*auth_option*] [, *user* [*auth_option*]] …
DEFAULT ROLE *role* [, *role* ] …
[REQUIRE {NONE | *tls_option* [[AND] *tls_option*] …}]
[WITH *resource_option* [*resource_option*] …]
[*password_option* | *lock_option*] …
[COMMENT \’*comment_string*\’ | ATTRIBUTE \’*json_object*\’]
*user*:
(see Section 8.2.4, “Specifying Account Names”)
*auth_option*: {
IDENTIFIED BY \’*auth_string*\’ [AND *2fa_auth_option*]
| IDENTIFIED BY RANDOM PASSWORD [AND *2fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* [AND *2fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* BY \’*auth_string*\’ [AND *2fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* BY RANDOM PASSWORD [AND *2fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* AS \’*auth_string*\’ [AND *2fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* [*initial_auth_option*]
}
*2fa_auth_option*: {
IDENTIFIED BY \’*auth_string*\’ [AND *3fa_auth_option*]
| IDENTIFIED BY RANDOM PASSWORD [AND *3fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* [AND *3fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* BY \’*auth_string*\’ [AND *3fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* BY RANDOM PASSWORD [AND *3fa_auth_option*]
| IDENTIFIED WITH *auth_plugin* AS \’*auth_string*\’ [AND *3fa_auth_option*]
}
*3fa_auth_option*: {
IDENTIFIED BY \’*auth_string*\’
| IDENTIFIED BY RANDOM PASSWORD
| IDENTIFIED WITH *auth_plugin*
| IDENTIFIED WITH *auth_plugin* BY \’*auth_string*\’
| IDENTIFIED WITH *auth_plugin* BY RANDOM PASSWORD
| IDENTIFIED WITH *auth_plugin* AS \’*auth_string*\’
}
*initial_auth_option*: {
INITIAL AUTHENTICATION IDENTIFIED BY {RANDOM PASSWORD | \’*auth_string*\’}
| INITIAL AUTHENTICATION IDENTIFIED WITH *auth_plugin* AS \’*auth_string*\’
}
*tls_option*: {
SSL
| X509
| CIPHER \’*cipher*\’
| ISSUER \’*issuer*\’
| SUBJECT \’*subject*\’
}
*resource_option*: {
MAX_QUERIES_PER_HOUR *count*
| MAX_UPDATES_PER_HOUR *count*
| MAX_CONNECTIONS_PER_HOUR *count*
| MAX_USER_CONNECTIONS *count*
}
*password_option*: {
PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL *N* DAY]
| PASSWORD HISTORY {DEFAULT | *N*}
| PASSWORD REUSE INTERVAL {DEFAULT | *N* DAY}
| PASSWORD REQUIRE CURRENT [DEFAULT | OPTIONAL]
| FAILED_LOGIN_ATTEMPTS *N*
| PASSWORD_LOCK_TIME {*N* | UNBOUNDED}
}
*lock_option*: {
ACCOUNT LOCK
| ACCOUNT UNLOCK
}

CREATE USER语句创建新的 MySQL 账户。它使得可以为新账户建立认证、角色、SSL/TLS、资源限制、密码管理、注释和属性属性。它还控制了账户最初是锁定还是解锁的状态。

要使用CREATE USER,您必须具有全局CREATE USER权限,或者对mysql系统模式具有INSERT权限。当启用read_only系统变量时,CREATE USER还需要CONNECTION_ADMIN权限(或已弃用的SUPER权限)。

截至 MySQL 8.0.27,以下附加特权考虑因素适用:

authentication_policy 系统变量对CREATE USER语句中与认证相关的子句的使用施加了一定的约束;详情请参阅该变量的描述。如果具有AUTHENTICATION_POLICY_ADMIN权限,则这些约束不适用。
要创建一个使用无密码认证的账户,您必须具有PASSWORDLESS_USER_ADMIN权限。

截至 MySQL 8.0.22,如果要创建的任何账户被命名为任何存储对象的DEFINER属性,则CREATE USER将失败并显示错误。(也就是说,如果创建账户会导致该账户接管当前孤立的存储对象,则该语句将失败。)要执行该操作,您必须具有SET_USER_ID权限;在这种情况下,该语句将以警告成功而不是错误失败。如果没有SET_USER_ID,要执行用户创建操作,请删除孤立对象,创建账户并授予其权限,然后重新创建已删除的对象。有关更多信息,包括如何识别哪些对象将给定账户命名为DEFINER属性,请参阅孤立存储对象。

CREATE USER 对所有命名用户都成功,或者如果发生任何错误则回滚并不起作用。默认情况下,如果尝试创建已存在的用户,则会发生错误。如果给出了 IF NOT EXISTS 子句,则该语句会对每个已存在的命名用户产生警告,而不是错误。

重要提示

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

CREATE USER 语句有几个方面,描述如下主题:

创建用户概述
创建用户认证选项
创建用户多因素认证选项
创建用户角色选项
创建用户 SSL/TLS 选项
创建用户资源限制选项
创建用户密码管理选项
创建用户注释和属性选项
创建用户账户锁定选项
创建用户二进制日志记录

创建用户概述

对于每个账户,CREATE USER 在 mysql.user 系统表中创建一行新记录。账户行反映了语句中指定的属性。未指定的属性将设置为它们的默认值:

认证:默认认证插件(如 默认认证插件 中所述确定的),以及空凭据
默认角色:NONE
SSL/TLS:NONE
资源限制:无限制
密码管理:PASSWORD EXPIRE DEFAULT PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT PASSWORD REQUIRE CURRENT DEFAULT;禁用了失败登录跟踪和临时帐户锁定
帐户锁定:ACCOUNT UNLOCK

创建时,帐户没有任何权限和默认角色NONE。要为此帐户分配权限或角色,请使用一个或多个GRANT语句。

每个帐户名称都采用第 8.2.4 节,“指定帐户名称”中描述的格式。例如:

CREATE USER \’jeffrey\’@\’localhost\’ IDENTIFIED BY \’*password*\’;

如果帐户名称的主机名部分被省略,则默认为\’%\’。您应该知道,虽然 MySQL 8.0 将授予此类用户的授权视为已授予\’*user*\’@\’localhost\’,但此行为已在 MySQL 8.0.35 中被弃用,并因此可能在将来的 MySQL 版本中被移除。

每个命名帐户的*user值后面可以跟一个可选的auth_option值,表示帐户的认证方式。这些值可以指定帐户认证插件和凭据(例如密码)。每个auth_option*值仅适用于紧随其后的帐户。

根据*user规范,语句可以包括 SSL/TLS、资源限制、密码管理和锁定属性的选项。所有这些选项都是语句的全局属性,并适用于语句中命名的所有*帐户。

示例:创建一个使用默认认证插件和给定密码的帐户。标记密码已过期,以便用户必须在首次连接到服务器时选择新密码:

CREATE USER \’jeffrey\’@\’localhost\’
IDENTIFIED BY \’*new_password*\’ PASSWORD EXPIRE;

示例:创建一个使用caching_sha2_password认证插件和给定密码的帐户。要求每 180 天选择一个新密码,并启用失败登录跟踪,以便三次连续输入错误密码导致帐户被临时锁定两天:

CREATE USER \’jeffrey\’@\’localhost\’
IDENTIFIED WITH caching_sha2_password BY \’*new_password*\’
PASSWORD EXPIRE INTERVAL 180 DAY
FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 2;

示例:创建多个帐户,指定一些每个帐户的属性和一些全局属性:

CREATE USER
\’jeffrey\’@\’localhost\’ IDENTIFIED WITH mysql_native_password
BY \’*new_password1*\’,
\’jeanne\’@\’localhost\’ IDENTIFIED WITH caching_sha2_password
BY \’*new_password2*\’
REQUIRE X509 WITH MAX_QUERIES_PER_HOUR 60
PASSWORD HISTORY 5
ACCOUNT LOCK;

每个*auth_option*值(在本例中为IDENTIFIED WITH … BY)仅适用于紧随其后的帐户,因此每个帐户使用紧随其后的认证插件和密码。

剩余的属性全局适用于语句中命名的所有帐户,因此对于两个帐户:

必须使用有效的 X.509 证书进行连接。
每小时最多允许 60 个查询。
密码更改不能重复使用最近的五个密码。
帐户最初被锁定,因此实际上它是一个占位符,直到管理员解锁它才能使用。

创建用户认证选项

帐户名称后面可以跟一个*auth_option*认证选项,指定帐户认证插件、凭据或两者。

注意

在 MySQL 8.0.27 之前,auth_option 定义了账户进行身份验证的唯一方法。也就是说,所有账户都使用单因素/单因素身份验证(1FA/SFA)。MySQL 8.0.27 及更高版本支持多因素身份验证(MFA),因此账户可以使用最多三种身份验证方法。也就是说,账户可以使用双因素身份验证(2FA)或三因素身份验证(3FA)。auth_option 的语法和语义保持不变,但*auth_option* 可以后跟额外身份验证方法的规范。本节描述了*auth_option*。有关可选 MFA 相关后续子句的详细信息,请参阅 CREATE USER 多因素身份验证选项。

注意

仅适用于使用将凭据存储在 MySQL 内部的身份验证插件的账户的随机密码生成子句。对于使用针对 MySQL 外部凭据系统执行身份验证的插件的账户,密码管理也必须在该系统外部处理。有关内部凭据存储的更多信息,请参阅 第 8.2.15 节,“密码管理”。

auth_plugin 指定了一个身份验证插件。插件名称可以是带引号的字符串文字或未带引号的名称。插件名称存储在 mysql.user 系统表的 plugin 列中。
对于未指定身份验证插件的*auth_option* 语法,服务器会分配默认插件,具体确定方法请参见 默认身份验证插件。有关每个插件的描述,请参见 第 8.4.1 节,“身份验证插件”。
存储在内部的凭据存储在 mysql.user 系统表中。\’*auth_string*\’ 值或 RANDOM PASSWORD 指定账户凭据,可以是明文(未加密)字符串或以与账户关联的身份验证插件期望的格式进行哈希处理:

对于使用 BY \’*auth_string*\’ 语法的情况,字符串是明文的,并传递给身份验证插件进行可能的哈希处理。插件返回的结果存储在 mysql.user 表中。插件可以按照指定的值使用该值,这种情况下不会发生哈希处理。
对于使用 BY RANDOM PASSWORD 语法的情况,MySQL 生成一个随机密码并以明文形式传递给身份验证插件进行可能的哈希处理。插件返回的结果存储在 mysql.user 表中。插件可以按照指定的值使用该值,这种情况下不会发生哈希处理。
随机生成的密码可在 MySQL 8.0.18 中使用,并具有随机密码生成中描述的特性。
对于使用AS \’*auth_string*\’语法的语法,假定字符串已经是认证插件所需的格式,并按原样存储在mysql.user表中。如果插件需要哈希值,则该值必须已经以适合插件的格式进行哈希处理;否则,插件无法使用该值,客户端连接的正确认证也不会发生。
截至 MySQL 8.0.17,哈希字符串可以是字符串文字或十六进制值。当启用print_identified_with_as_hex系统变量时,后者对应于包含不可打印字符的密码哈希的值类型,该变量由SHOW CREATE USER显示。
如果认证插件不对认证字符串进行哈希处理,则BY \’*auth_string*\’和AS \’*auth_string*\’子句具有相同的效果:认证字符串按原样存储在mysql.user系统表中。

CREATE USER允许这些*auth_option*语法:

IDENTIFIED BY \’*auth_string*\’
将帐户认证插件设置为默认插件,将明文\’*auth_string*\’值传递给插件进行可能的哈希处理,并将结果存储在mysql.user系统表中的帐户行中。
IDENTIFIED BY RANDOM PASSWORD
将帐户认证插件设置为默认插件,生成随机密码,将明文密码值传递给插件进行可能的哈希处理,并将结果存储在mysql.user系统表中的帐户行中。该语句还将明文密码作为结果集返回,以便用户或执行该语句的应用程序可以使用。有关结果集和随机生成密码的特性的详细信息,请参见随机密码生成。
IDENTIFIED WITH *auth_plugin*
将帐户认证插件设置为*auth_plugin*,将凭据清除为空字符串,并将结果存储在mysql.user系统表中的帐户行中。
IDENTIFIED WITH *auth_plugin* BY \’*auth_string*\’
将帐户认证插件设置为*auth_plugin*,将明文\’*auth_string*\’值传递给插件进行可能的哈希处理,并将结果存储在mysql.user系统表中的帐户行中。
IDENTIFIED WITH *auth_plugin* BY RANDOM PASSWORD
将账户认证插件设置为 auth_plugin,生成一个随机密码,将明文密码值传递给插件进行可能的哈希处理,并将结果存储在 mysql.user 系统表中的账户行中。该语句还将明文密码作为结果集返回,以便用户或执行该语句的应用程序可以访问。有关结果集和随机生成密码的特性的详细信息,请参阅 随机密码生成。
IDENTIFIED WITH *auth_plugin* AS \’*auth_string*\’
将账户认证插件设置为 auth_plugin,并将 \’*auth_string*\’ 值原样存储在 mysql.user 账户行中。如果插件需要哈希字符串,则假定字符串已经以插件所需的格式进行了哈希处理。

示例:将密码指定为明文;使用默认插件:

CREATE USER \’jeffrey\’@\’localhost\’
IDENTIFIED BY \’*password*\’;

示例:指定认证插件,以及明文密码值:

CREATE USER \’jeffrey\’@\’localhost\’
IDENTIFIED WITH mysql_native_password BY \’*password*\’;

在每种情况下,存储在账户行中的密码值是与账户关联的认证插件对其进行哈希后的明文值 \’*password*\’。

有关设置密码和认证插件的其他信息,请参阅 第 8.2.14 节,“分配账户密码” 和 第 8.2.17 节,“可插拔认证”。

创建用户多因素认证选项

CREATE USER 中的 auth_option 部分定义了一种用于单因素认证(1FA/SFA)的认证方法。从 MySQL 8.0.27 开始,CREATE USER 具有支持多因素认证(MFA)的子句,因此账户可以拥有最多三种认证方法。也就是说,账户可以使用双因素认证(2FA)或三因素认证(3FA)。

authentication_policy 系统变量定义了带有多因素认证(MFA)子句的 CREATE USER 语句的约束条件。例如,authentication_policy 设置控制了账户可以拥有的认证因素数量,以及对于每个因素,允许使用的认证方法。请参阅 配置多因素认证策略。

关于确定未指定插件名称的认证子句的默认认证插件的特定规则的信息,请参见默认认证插件。

在*auth_option*之后,可能会出现不同的可选 MFA 子句:

2fa_auth_option:指定二要素认证方法。以下示例将caching_sha2_password定义为第一要素认证方法,将authentication_ldap_sasl定义为第二要素认证方法。
CREATE USER \’u1\’@\’localhost\’
IDENTIFIED WITH caching_sha2_password
BY \’*sha2_password*\’
AND IDENTIFIED WITH authentication_ldap_sasl
AS \’uid=u1_ldap,ou=People,dc=example,dc=com\’;
3fa_auth_option:在*2fa_auth_option之后,可能会出现一个3fa_auth_option*子句,用于指定第三要素认证方法。以下示例将caching_sha2_password定义为第一要素认证方法,将authentication_ldap_sasl定义为第二要素认证方法,将authentication_fido定义为第三要素认证方法。
CREATE USER \’u1\’@\’localhost\’
IDENTIFIED WITH caching_sha2_password
BY \’*sha2_password*\’
AND IDENTIFIED WITH authentication_ldap_sasl
AS \’uid=u1_ldap,ou=People,dc=example,dc=com\’
AND IDENTIFIED WITH authentication_fido;
initial_auth_option:指定用于配置 FIDO 无密码认证的初始认证方法。如下所示,需要使用生成的随机密码或用户指定的*auth-string*进行临时认证,以启用 FIDO 无密码认证。
CREATE USER *user*
IDENTIFIED WITH authentication_fido
INITIAL AUTHENTICATION IDENTIFIED BY {RANDOM PASSWORD | \’*auth_string*\’};
有关使用 FIDO 可插拔认证配置无密码认证的信息,请参见 FIDO 无密码认证。

创建用户角色选项

DEFAULT ROLE子句定义了用户连接到服务器并进行身份验证时或用户在会话期间执行SET ROLE DEFAULT语句时激活的角色。

每个角色名称使用第 8.2.5 节,“指定角色名称”中描述的格式。例如:

CREATE USER \’joe\’@\’10.0.0.1\’ DEFAULT ROLE administrator, developer;

如果省略角色名称的主机名部分,默认为\’%\’。

DEFAULT ROLE子句允许一个或多个逗号分隔的角色名称列表。这些角色必须在执行CREATE USER时存在;否则语句会引发错误(ER_USER_DOES_NOT_EXIST),并且用户不会被创建。

创建用户 SSL/TLS 选项

MySQL 可以检查 X.509 证书属性,除了基于用户名和凭据的通常认证外。有关在 MySQL 中使用 SSL/TLS 的背景信息,请参见第 8.3 节,“使用加密连接”。

要为 MySQL 账户指定与 SSL/TLS 相关的选项,请使用指定一个或多个*tls_option*值的REQUIRE子句。

REQUIRE选项的顺序不重要,但不能指定两次选项。REQUIRE选项之间的AND关键字是可选的。

CREATE USER 允许这些 tls_option 值:

NONE
表示语句指定的所有帐户没有 SSL 或 X.509 要求。如果用户名和密码有效,则允许未加密连接。如果客户端具有正确的证书和密钥文件,则客户端可以选择使用加密连接。
CREATE USER \’jeffrey\’@\’localhost\’ REQUIRE NONE;
客户端默认尝试建立安全连接。对于具有 REQUIRE NONE 的客户端,如果无法建立安全连接,则连接尝试回退到未加密连接。要求加密连接,客户端只需指定 –ssl-mode=REQUIRED 选项;如果无法建立安全连接,则连接尝试失败。
如果未指定任何与 SSL 相关的 REQUIRE 选项,则 NONE 是默认值。
SSL
通知服务器只允许通过语句指定的所有帐户进行加密连接。
CREATE USER \’jeffrey\’@\’localhost\’ REQUIRE SSL;
客户端默认尝试建立安全连接。对于具有 REQUIRE SSL 的帐户,如果无法建立安全连接,则连接尝试失败。
X509
对于语句指定的所有帐户,要求客户端提供有效证书,但确切的证书、颁发者和主题并不重要。唯一的要求是应该能够使用其中一个 CA 证书验证其签名。使用 X.509 证书始终意味着加密,因此在这种情况下 SSL 选项是不必要的。
CREATE USER \’jeffrey\’@\’localhost\’ REQUIRE X509;
对于具有 REQUIRE X509 的帐户,客户端必须指定 –ssl-key 和 –ssl-cert 选项进行连接。(建议但不是必须还指定 –ssl-ca,以便验证服务器提供的公共证书。)对于 ISSUER 和 SUBJECT 也是如此,因为这些 REQUIRE 选项暗示了 X509 的要求。
ISSUER \’*issuer*\’
对于语句指定的所有帐户,要求客户端提供由 CA \’*issuer*\’ 颁发的有效 X.509 证书。如果客户端提供的证书有效但颁发者不同,则服务器拒绝连接。使用 X.509 证书始终意味着加密,因此在这种情况下 SSL 选项是不必要的。
CREATE USER \’jeffrey\’@\’localhost\’
REQUIRE ISSUER \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL/CN=CA/emailAddress=ca@example.com\’;
因为 ISSUER 暗示了 X509 的要求,客户端必须指定 –ssl-key 和 –ssl-cert 选项进行连接。(建议但不是必须还指定 –ssl-ca,以便验证服务器提供的公共证书。)
SUBJECT \’*subject*\’
对于陈述中命名的所有帐户,要求客户端提供包含主题*subject*的有效 X.509 证书。如果客户端提供了一个有效但主题不同的证书,服务器将拒绝连接。使用 X.509 证书总是意味着加密,因此在这种情况下SSL选项是不必要的。
CREATE USER \’jeffrey\’@\’localhost\’
REQUIRE SUBJECT \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL demo client certificate/
CN=client/emailAddress=client@example.com\’;
MySQL 对\’*subject*\’值与证书中的值进行简单的字符串比较,因此字母大小写和组件顺序必须与证书中的完全一致。
因为SUBJECT暗示了X509的要求,客户端必须指定–ssl-key和–ssl-cert选项进行连接。(建议但不是必须还指定–ssl-ca,以便验证服务器提供的公共证书。)
CIPHER \’*cipher*\’
对于陈述中命名的所有帐户,需要为加密连接指定特定的密码方法。这个选项是必需的,以确保使用足够强度的密码和密钥长度。如果使用旧算法和短加密密钥,加密可能会很弱。
CREATE USER \’jeffrey\’@\’localhost\’
REQUIRE CIPHER \’EDH-RSA-DES-CBC3-SHA\’;

SUBJECT、ISSUER和CIPHER选项可以在REQUIRE子句中组合使用:

CREATE USER \’jeffrey\’@\’localhost\’
REQUIRE SUBJECT \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL demo client certificate/
CN=client/emailAddress=client@example.com\’
AND ISSUER \’/C=SE/ST=Stockholm/L=Stockholm/
O=MySQL/CN=CA/emailAddress=ca@example.com\’
AND CIPHER \’EDH-RSA-DES-CBC3-SHA\’;

创建用户资源限制选项

可以通过讨论中提到的第 8.2.21 节,“设置帐户资源限制”来限制帐户对服务器资源的使用。为此,请使用指定一个或多个*resource_option*值的WITH子句。

WITH选项的顺序无关紧要,除非给定资源限制被多次指定,最后一次实例优先。

CREATE USER允许这些*resource_option*值:

MAX_QUERIES_PER_HOUR *count*,MAX_UPDATES_PER_HOUR *count*,MAX_CONNECTIONS_PER_HOUR *count*
对于陈述中命名的所有帐户,这些选项限制了每个帐户在任何给定的一个小时内对服务器的查询、更新和连接的次数。如果*count*是0(默认值),这意味着该帐户没有限制。
MAX_USER_CONNECTIONS *count*
对于陈述中命名的所有帐户,限制了每个帐户对服务器的最大同时连接数。非零的*count明确指定了该帐户的限制。如果count*是0(默认值),服务器从max_user_connections系统变量的全局值确定该帐户的同时连接数。如果max_user_connections也是零,则该帐户没有限制。

示例:

CREATE USER \’jeffrey\’@\’localhost\’
WITH MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;

创建用户密码管理选项

创建用户 支持几个*password_option*值用于密码管理:

密码过期选项:您可以手动使账户密码过期并建立其密码过期策略。策略选项不会使密码过期。相反,它们确定服务器如何根据密码年龄自动使账户过期,密码年龄是从最近一次账户密码更改的日期和时间开始评估的。
密码重用选项:您可以基于密码更改次数、经过的时间或两者限制密码重用。
需要密码验证的选项:您可以指示尝试更改账户密码是否必须指定当前密码,以验证试图进行更改的用户实际上知道当前密码。
不正确密码失败登录跟踪选项:您可以导致服务器跟踪失败的登录尝试,并临时锁定给出太多连续不正确密码的账户。失败次数和锁定时间可配置。

本节描述了密码管理选项的语法。有关建立密码管理策略的信息,请参阅第 8.2.15 节,“密码管理”。

如果指定了给定类型的多个密码管理选项,则最后一个优先。例如,密码过期默认 密码过期从不等同于密码过期从不。

注意

除了与失败登录跟踪相关的选项外,密码管理选项仅适用于使用将凭据存储在 MySQL 内部的身份验证插件的账户。对于使用针对 MySQL 外部凭据系统执行身份验证的插件的账户,密码管理也必须在该系统外部处理。有关内部凭据存储的更多信息,请参阅第 8.2.15 节,“密码管理”。

如果账户密码已被手动过期或密码年龄被认为大于其允许的生命周期根据自动过期策略。在这种情况下,服务器要么断开客户端连接,要么限制其允许的操作(请参阅第 8.2.16 节,“过期密码的服务器处理”)。受限客户端执行的操作会导致错误,直到用户建立新的账户密码。

创建用户 允许这些*password_option*值来控制密码过期:

密码过期
立即标记语句命名的所有账户的密码过期。
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE;
密码过期默认
设置所有语句中命名的帐户,使全局过期策略适用,如default_password_lifetime系统变量指定的那样。
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE DEFAULT;
PASSWORD EXPIRE NEVER
此过期选项覆盖了语句中命名的所有帐户的全局策略。对于每个帐户,它禁用密码过期,使密码永不过期。
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE NEVER;
PASSWORD EXPIRE INTERVAL *N* DAY
此过期选项覆盖了语句中命名的所有帐户的全局策略。对于每个帐户,它将密码寿命设置为*N*天。以下语句要求每 180 天更改一次密码:
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD EXPIRE INTERVAL 180 DAY;

CREATE USER允许这些*password_option*值来控制基于所需最小密码更改次数的先前密码重用:

PASSWORD HISTORY DEFAULT
设置所有语句中命名的帐户,使全局关于密码历史长度的策略适用,以禁止在password_history系统变量指定的更改次数之前重用密码。
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD HISTORY DEFAULT;
PASSWORD HISTORY *N*
此历史长度选项覆盖了语句中命名的所有帐户的全局策略。对于每个帐户,它将密码历史长度设置为*N个密码,以禁止重用最近选择的N*个密码中的任何一个。以下语句禁止重用之前的 6 个密码中的任何一个:
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD HISTORY 6;

CREATE USER允许这些*password_option*值来控制基于经过时间的先前密码重用:

PASSWORD REUSE INTERVAL DEFAULT
设置所有帐户中命名的语句,使全局关于经过时间的策略适用,以禁止重用新于password_reuse_interval系统变量指定的天数的密码。
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD REUSE INTERVAL DEFAULT;
PASSWORD REUSE INTERVAL *N* DAY
此经过时间选项覆盖了语句中命名的所有帐户的全局策略。对于每个帐户,它将密码重用间隔设置为*N*天,以禁止重用新于该天数的密码。以下语句禁止密码在 360 天内重用:
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD REUSE INTERVAL 360 DAY;

CREATE USER允许这些*password_option*值来控制是否尝试更改帐户密码必须指定当前密码,以验证尝试进行更改的用户实际上知道当前密码:

PASSWORD REQUIRE CURRENT
此验证选项覆盖了语句中命名的所有帐户的全局策略。对于每个帐户,它要求密码更改时指定当前密码。
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD REQUIRE CURRENT;
PASSWORD REQUIRE CURRENT OPTIONAL
此验证选项会覆盖语句指定的所有帐户的全局策略。对于每个帐户,不需要密码更改指定当前密码。(当前密码可以给出,但不是必需的。)
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD REQUIRE CURRENT OPTIONAL;
PASSWORD REQUIRE CURRENT DEFAULT
设置所有由帐户命名的语句,以便全局关于密码验证的策略适用,如password_require_current 系统变量所指定的那样。
CREATE USER \’jeffrey\’@\’localhost\’ PASSWORD REQUIRE CURRENT DEFAULT;

从 MySQL 8.0.19 开始,CREATE USER 允许这些 password_option 值来控制登录失败跟踪:

FAILED_LOGIN_ATTEMPTS *N*
是否跟踪指定错误密码的帐户登录尝试。N 必须是从 0 到 32767 的数字。值为 0 会禁用登录失败跟踪。大于 0 的值表示多少连续密码失败会导致临时帐户锁定(如果 PASSWORD_LOCK_TIME 也是非零)。
PASSWORD_LOCK_TIME {*N* | UNBOUNDED}
连续登录尝试提供错误密码后锁定帐户的时间。N 必须是从 0 到 32767 的数字,或者 UNBOUNDED。值为 0 会禁用临时帐户锁定。大于 0 的值表示锁定帐户的天数。值为 UNBOUNDED 会导致帐户锁定持续时间无限制;一旦锁定,帐户将保持锁定状态直到解锁。有关解锁发生的条件的信息,请参阅登录失败跟踪和临时帐户锁定。

要进行登录失败跟踪和临时锁定,帐户的 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 选项都必须非零。以下语句创建一个帐户,在连续四次密码失败后保持锁定两天:

CREATE USER \’jeffrey\’@\’localhost\’
FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 2;

创建用户注释和属性选项

从 MySQL 8.0.21 开始,您可以创建一个带有可选注释或属性的帐户,如下所述:

用户注释
要设置用户注释,请在 CREATE USER 语句中添加 COMMENT \’*user_comment*\’,其中 user_comment 是用户注释的文本。
示例(省略其他选项):
CREATE USER \’jon\’@\’localhost\’ COMMENT \’Some information about Jon\’;
用户属性
用户属性是由一个或多个键值对组成的 JSON 对象,并通过在 CREATE USER 中包含 ATTRIBUTE \’*json_object*\’ 来设置。json_object 必须是一个有效的 JSON 对象。
示例(省略其他选项):
CREATE USER \’jim\’@\’localhost\’
ATTRIBUTE \'{\”fname\”: \”James\”, \”lname\”: \”Scott\”, \”phone\”: \”123-456-7890\”}\’;

用户注释和用户属性一起存储在信息模式 USER_ATTRIBUTES 表的 ATTRIBUTE 列中。此查询显示了刚刚用于创建用户 jim@localhost 的语句插入的此表中的行:

mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER = \’jim\’ AND HOST = \’localhost\’\\G
*************************** 1\\. row ***************************
USER: jim
HOST: localhost
ATTRIBUTE: {\”fname\”: \”James\”, \”lname\”: \”Scott\”, \”phone\”: \”123-456-7890\”} 1 row in set (0.00 sec)

实际上,COMMENT选项提供了一个快捷方式,用于设置一个只有comment作为其键且其值为选项提供的参数的用户属性。通过执行语句CREATE USER \’jon\’@\’localhost\’ COMMENT \’Some information about Jon\’,并观察它插入到USER_ATTRIBUTES表中的行,您可以看到这一点:

mysql> CREATE USER \’jon\’@\’localhost\’ COMMENT \’Some information about Jon\’;
Query OK, 0 rows affected (0.06 sec)
mysql> SELECT * FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER = \’jon\’ AND HOST = \’localhost\’;
+——+———–+——————————————-+
| USER | HOST | ATTRIBUTE |
+——+———–+——————————————-+
| jon | localhost | {\”comment\”: \”Some information about Jon\”} |
+——+———–+——————————————-+
1 row in set (0.00 sec)

不能在同一CREATE USER语句中同时使用COMMENT和ATTRIBUTE;尝试这样做会导致语法错误。要同时设置用户评论和用户属性,使用ATTRIBUTE并在其参数中包含具有comment键的值,如下所示:

mysql> CREATE USER \’bill\’@\’localhost\’
-> ATTRIBUTE \'{\”fname\”:\”William\”, \”lname\”:\”Schmidt\”,
-> \”comment\”:\”Website developer\”}\’;
Query OK, 0 rows affected (0.16 sec)

由于ATTRIBUTE行的内容是一个 JSON 对象,您可以使用任何适当的 MySQL JSON 函数或运算符来操作它,如下所示:

mysql> SELECT
-> USER AS User,
-> HOST AS Host,
-> CONCAT(ATTRIBUTE->>\”$.fname\”,\” \”,ATTRIBUTE->>\”$.lname\”) AS \’Full Name\’,
-> ATTRIBUTE->>\”$.comment\” AS Comment
-> FROM INFORMATION_SCHEMA.USER_ATTRIBUTES
-> WHERE USER=\’bill\’ AND HOST=\’localhost\’;
+——+———–+—————–+——————-+
| User | Host | Full Name | Comment |
+——+———–+—————–+——————-+
| bill | localhost | William Schmidt | Website developer |
+——+———–+—————–+——————-+
1 row in set (0.00 sec)

要为现有用户设置或更改用户评论或用户属性,可以使用带有ALTER USER语句的COMMENT或ATTRIBUTE选项。

因为用户评论和用户属性在单个JSON列中内部存储在一起,这为它们的最大组合大小设置了一个上限;有关更多信息,请参阅 JSON 存储要求。

有关更多信息和示例,请参阅信息模式USER_ATTRIBUTES表的描述。

创建用户帐户锁定选项

MySQL 支持使用ACCOUNT LOCK和ACCOUNT UNLOCK选项对帐户进行锁定和解锁,这些选项指定帐户的锁定状态。有关更多讨论,请参阅 Section 8.2.20,“帐户锁定”。

如果指定了多个帐户锁定选项,则最后一个优先。

创建用户二进制日志

如果CREATE USER成功,则写入二进制日志,但如果失败则不写入;在这种情况下,将发生回滚并且不会进行任何更改。写入二进制日志的语句包括所有命名用户。如果给出了IF NOT EXISTS子句,这甚至包括已经存在且未创建的用户。

写入二进制日志的语句为每个用户指定一个身份验证插件,确定如下:

原始语句中指定的插件。
否则,默认的身份验证插件。特别是,如果用户u1已经存在并使用非默认身份验证插件,则为CREATE USER IF NOT EXISTS u1写入二进制日志的语句将列出默认身份验证插件。(如果必须为用户指定非默认身份验证插件,请在原始语句中包含它。)

如果服务器为二进制日志中写入的任何不存在的用户添加默认身份验证插件,则会在错误日志中写入警告,列出这些用户的名称。

如果原始语句指定了FAILED_LOGIN_ATTEMPTS或PASSWORD_LOCK_TIME选项,则写入二进制日志的语句将包括该选项。

支持多因素认证(MFA)的子句的CREATE USER语句将写入二进制日志。

CREATE USER … IDENTIFIED WITH .. INITIAL AUTHENTICATION IDENTIFIED WITH …语句将作为CREATE USER .. IDENTIFIED WITH .. INITIAL AUTHENTICATION IDENTIFIED WITH .. AS \’*password-hash*\’写入二进制日志,其中*password-hash是用户指定的auth-string*或服务器在指定RANDOM PASSWORD子句时生成的随机密码。

原文:dev.mysql.com/doc/refman/8.0/en/drop-role.html

15.7.1.4 DROP ROLE Statement

DROP ROLE [IF EXISTS] *role* [, *role* ] …

DROP ROLE 移除一个或多个角色(具有特权的命名集合)。要使用此语句,您必须具有全局DROP ROLE或CREATE USER特权。当启用read_only系统变量时,DROP ROLE 还需要CONNECTION_ADMIN特权(或已弃用的SUPER特权)。

从 MySQL 8.0.16 开始,具有CREATE USER特权的用户可以使用此语句删除已锁定或未锁定的账户。具有DROP ROLE特权的用户只能使用此语句删除已锁定的账户(未锁定的账户可能是用于登录到服务器的用户账户,而不仅仅是角色)。

在mandatory_roles系统变量值中命名的角色不能被删除。

DROP ROLE 对所有命名角色要么成功,要么回滚并且如果发生任何错误则不会产生影响。默认情况下,如果尝试删除不存在的角色,则会发生错误。如果给出了IF EXISTS子句,则该语句会对每个不存在的命名角色产生警告,而不是错误。

如果成功,该语句将被写入二进制日志,但如果失败则不会;在这种情况下,将发生回滚并且不会进行任何更改。写入二进制日志的语句包括所有命名角色。如果给出了IF EXISTS子句,则即使是不存在且未被删除的角色也会被包括在内。

每个角色名称使用第 8.2.5 节“指定角色名称”中描述的格式。例如:

DROP ROLE \’admin\’, \’developer\’;
DROP ROLE \’webapp\’@\’localhost\’;

如果省略角色名称的主机名部分,默认为\’%\’。

一个被撤销的角色会自动从授予该角色的任何用户账户(或角色)中撤销。在该账户的任何当前会话中,其调整后的特权将从执行下一个语句开始生效。

有关角色使用示例,请参见第 8.2.10 节“使用角色”。

原文:dev.mysql.com/doc/refman/8.0/en/drop-user.html

15.7.1.5 DROP USER 语句

DROP USER [IF EXISTS] *user* [, *user*] …

DROP USER 语句会移除一个或多个 MySQL 账户及其权限。它会从所有授权表中移除该账户的权限行。

在 mandatory_roles 系统变量值中命名的角色不能被删除。

要使用 DROP USER,你必须拥有全局的 CREATE USER 权限,或者对 mysql 系统模式拥有 DELETE 权限。当启用 read_only 系统变量时,DROP USER 还需要 CONNECTION_ADMIN 权限(或者已弃用的 SUPER 权限)。

截至 MySQL 8.0.22 版本,如果要删除的任何账户被命名为任何存储对象的 DEFINER 属性,则 DROP USER 会因错误而失败。(也就是说,如果删除一个账户会导致存储对象变成孤立状态,则该语句会失败。)要执行该操作,你必须拥有 SET_USER_ID 权限;在这种情况下,该语句会成功并产生警告,而不是失败并产生错误。有关更多信息,包括如何识别哪些对象将给定账户命名为 DEFINER 属性,请参阅 Orphan Stored Objects。

DROP USER 对所有命名用户要么全部成功,要么回滚并且在发生任何错误时不会产生影响。默认情况下,如果尝试删除不存在的用户,则会发生错误。如果给出了 IF EXISTS 子句,则该语句会对每个不存在的命名用户产生警告,而不是错误。

如果成功,该语句会被写入二进制日志,但如果失败则不会;在这种情况下,会发生回滚并且不会有任何更改。写入二进制日志的语句包括所有命名用户。如果给出了 IF EXISTS 子句,则即使用户不存在且未被删除,也会包括这些用户。

每个账户名使用 Section 8.2.4, “Specifying Account Names” 中描述的格式。例如:

DROP USER \’jeffrey\’@\’localhost\’;

如果省略账户名的主机名部分,则默认为 \’%\’。

重要提示

DROP USER 不会自动关闭任何打开的用户会话。相反,如果删除具有打开会话的用户,则该语句直到该用户的会话关闭后才生效。一旦会话关闭,用户被删除,该用户的下一次登录尝试将失败。这是设计上的。

DROP USER 不会自动删除或使旧用户创建的数据库或其中的对象失效。这包括DEFINER属性指定已删除用户的存储过程或视图。如果在定义者安全上下文中执行这些对象,可能会产生错误。(有关安全上下文的信息,请参见第 27.6 节,“存储对象访问控制”。)

原文:dev.mysql.com/doc/refman/8.0/en/grant.html

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 概述
对象引用指南
账户名称
MySQL 支持的特权
全局特权
数据库特权
表特权
列特权
存储过程特权
代理用户特权
授予角色
AS 子句和特权限制
其他账户特性
MySQL 和标准 SQL 版本的 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相关,允许管理员撤销账户特权。参见 Section 15.7.1.8, “REVOKE Statement”。

每个账户名称使用 Section 8.2.4, “Specifying Account Names”中描述的格式。每个角色名称使用 Section 8.2.5, “Specifying Role Names”中描述的格式。例如:

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。参见 Section 15.7.7.21, “SHOW GRANTS Statement”。

重要提示

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

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

警告

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

对象引用指南

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

要指定引用值:

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

有关字符串引用和标识符引用的指南,请参阅第 11.1.1 节,“字符串文字”和第 11.2 节,“模式对象名称”。

重要

如下几段所述的通配符字符%和_在 MySQL 8.0.35 中已被弃用,因此可能在未来的 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.0.37-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的安装中避免未转义的通配符字符在权限分配中出现。有关更多信息,请参见 Section 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 8.0.35 及更高版本中已弃用,并可能在将来的 MySQL 版本中删除。

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

GRANT ALL ON test.* TO \’\’@\’localhost\’ …;

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

有关帐户名称中用户名和主机名值的附加信息,请参阅 Section 8.2.4, “Specifying Account Names”。

警告

如果允许本地匿名用户连接到 MySQL 服务器,则还应将所有本地用户的权限授予为\’*user_name*\’@\’localhost\’。否则,当命名用户尝试从本地计算机登录到 MySQL 服务器时,将在mysql.user系统表中使用localhost的匿名用户帐户。有关详细信息,请参阅 Section 8.2.6, “Access Control, Stage 1: Connection Verification”。

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

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

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

DROP USER \’\’@\’localhost\’;

MySQL 支持的权限

以下表总结了可以为GRANT和REVOKE语句指定的静态和动态*priv_type*权限类型,以及可以授予每个权限的级别。有关每个权限的更多信息,请参阅 Section 8.2.2, “Privileges Provided by MySQL”。有关静态和动态权限之间的区别,请参阅 Static Versus Dynamic Privileges。

Table 15.11 Permissible Static Privileges for GRANT and REVOKE

权限意义和可授予级别ALL [PRIVILEGES]在指定的访问级别授予所有权限,除了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“无权限”的同义词权限含义和可授权级别
表 15.12 GRANT 和 REVOKE 的可允许动态权限

Privilege意义和可授权级别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启用设置受限会话系统变量。级别:全局。SET_USER_ID启用设置非自身DEFINER值。级别:全局。SHOW_ROUTINE启用访问存储过程定义。级别:全局。SKIP_QUERY_REWRITE不重写此用户执行的查询。级别:全局。SYSTEM_USER指定帐户为系统帐户。级别:全局。SYSTEM_VARIABLES_ADMIN启用修改或持久化全局系统变量。级别:全局。TABLE_ENCRYPTION_ADMIN启用覆盖默认加密设置。级别:全局。TELEMETRY_LOG_ADMIN启用在 AWS 上配置 MySQL HeatWave 的遥测日志。级别:全局。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;

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

从 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的账户访问是只读的。

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

如果您为任何用户使用表、列或例程权限,服务器会检查所有用户的表、列和例程权限,这会稍微减慢 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创建的表,即使表名匹配。有关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子句时)的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权限。有关详细信息和示例,请参见第 8.2.19 节,“代理用户”。

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

授予角色

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

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 级别可见,尽管其主要目的是通过在二进制日志中显示部分撤销者强加的授权限制,从而实现所有节点之间的统一复制。有关部分撤销的信息,请参见第 8.2.12 节,“使用部分撤销进行权限限制”。

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

这些条件适用于AS *user*子句:

当命名的*user*具有权限限制时,AS才会生效(这意味着partial_revokes系统变量已启用)。
如果给定了WITH ROLE,则必须将所有命名的角色授予命名的*user*。
命名的*user*应该是一个 MySQL 帐户,指定为\’*user_name*\’@\’*host_name*\’,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,所以这不包括在授予的权限中。
这里的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 权限。如果这样做,用户可以尝试通过重命名表来破坏权限系统!

有关与特定权限相关的安全风险的更多信息,请参阅 Section 8.2.2, “Privileges Provided by MySQL”。

MySQL 和标准 SQL 版本的 GRANT

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

MySQL 将权限与主机名和用户名的组合关联起来,而不仅仅是用户名。
标准 SQL 没有全局或数据库级别的权限,也不支持 MySQL 支持的所有权限类型。
MySQL 不支持标准 SQL 的 UNDER 权限。
标准 SQL 权限以分层方式结构化。如果您移除一个用户,该用户被授予的所有权限都将被撤销。如果您在 MySQL 中使用 DROP USER 也是如此。请参阅 Section 15.7.1.5, “DROP USER Statement”。
在标准 SQL 中,当您删除一个表时,该表的所有权限都将被撤销。在标准 SQL 中,当您撤销一个权限时,基于该权限授予的所有权限也将被撤销。在 MySQL 中,权限可以通过 DROP USER 或 REVOKE 语句来撤销。
在 MySQL 中,可以仅对表中的某些列拥有INSERT权限。在这种情况下,只要您为拥有INSERT权限的列插入值,您仍然可以在表上执行INSERT语句。如果严格 SQL 模式未启用,则省略的列将设置为它们的隐式默认值。在严格模式下,如果任何省略的列没有默认值,则该语句将被拒绝。(标准 SQL 要求您对所有列都拥有INSERT权限。)有关严格 SQL 模式和隐式默认值的信息,请参见第 7.1.11 节,“服务器 SQL 模式”和第 13.6 节,“数据类型默认值”。

#以上关于MySQL8 中文参考(六十四)的相关内容来源网络仅供参考,相关信息请以官方公告为准!

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92460.html

Like (0)
CSDN的头像CSDN
Previous 2024年6月27日
Next 2024年6月27日

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注