Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

8.2.3 授权表

mysql 系统数据库包括几个授权表,包含用户账户和它们持有的权限信息。本节描述这些表。有关系统数据库中的其他表的信息,请参阅 第 7.3 节,“mysql 系统架构”

这里的讨论描述了授权表的底层结构和服务器如何在与客户端交互时使用它们的内容。但是,通常您不直接修改授权表。修改是间接地通过使用账户管理语句,如 CREATE USERGRANTREVOKE,来设置账户和控制每个账户的权限。请参阅 第 15.7.1 节,“账户管理语句”。当您使用这些语句来执行账户操作时,服务器将代表您修改授权表。

Note

使用语句,如 INSERTUPDATEDELETE,直接修改授权表是被禁止的,并且是在您自己的风险下进行的。服务器可以忽略由于这种修改而变得畸形的行。

对于任何修改授权表的操作,服务器都会检查表是否具有预期的结构,并在不符合时产生错误。要更新表以达到预期的结构,请执行 MySQL 升级过程。请参阅 第 3 章,《升级 MySQL》

授权表概述

这些 mysql 数据库表包含授权信息:

有关静态和动态全局权限之间的差异的信息,请参阅 静态与动态权限

在 MySQL 8.3 中,授予权限表使用 InnoDB 存储引擎并且是事务性的。在 MySQL 8.3 之前,授予权限表使用 MyISAM 存储引擎并且是非事务性的。该更改使得伴随着账户管理语句的行为发生变化,例如 CREATE USERGRANT。以前,一个账户管理语句可以成功地命名多个用户,而现在,每个语句都是事务性的,或者成功地命名所有用户,或者回滚并且不产生任何效果。

每个授予权限表包含范围列和权限列:

  • 范围列确定每行在表中的作用域,即应用的上下文。例如,user 表的一行具有 HostUser 值的 'h1.example.net''bob',适用于从主机 h1.example.net 连接到服务器的认证连接,客户端指定的用户名为 bob。类似地,db 表的一行具有 HostUserDb 列值的 'h1.example.net''bob''reports',适用于 bob 从主机 h1.example.net 连接到服务器以访问 reports 数据库。 tables_privcolumns_priv 表包含范围列,指示每行应用于哪些表或表/列组合。 procs_priv 范围列指示每行应用于哪些存储过程。

  • 权限列指示每行授予的权限,即允许执行的操作。服务器将各种授予权限表中的信息组合成用户的完整权限描述。第 8.2.7 节,“访问控制,第二阶段:请求验证” 描述了这些规则。

此外,授予权限表可能包含用于其他目的的列,而不仅仅是范围或权限评估。

服务器使用授予权限表的方式如下:

  • user 表的范围列确定是否拒绝或允许传入连接。对于允许的连接,user 表中的任何权限授予都表示用户的静态全局权限。该表中的任何权限授予都适用于服务器上的所有数据库。

    Caution

    因为任何静态全局权限都被视为所有数据库的权限,因此任何静态全局权限都使用户能够使用 SHOW DATABASES 或检查 SCHEMATA 表中的数据库名称,除非数据库在数据库级别受到部分撤销的限制。

  • global_grants 表列出了当前分配给用户账户的动态全局权限。对于每行,范围列确定哪个用户拥有权限列中的权限。

  • db 表的范围列确定哪些用户可以从哪些主机访问哪些数据库。权限列确定允许的操作。数据库级别的权限授予适用于数据库和数据库中的所有对象,例如表和存储程序。

  • tables_privcolumns_privdb 表类似,但它们更细粒度:它们在表和列级别上应用,而不是在数据库级别上。表级别上的权限授予适用于该表及其所有列。列级别上的权限授予仅适用于特定列。

  • procs_priv 适用于存储例程(存储过程和函数)。routine 级别上的权限授予仅适用于单个过程或函数。

  • proxies_priv 指示哪些用户可以代理其他用户,并且用户是否可以授予其他用户 PROXY 权限。

  • default_rolesrole_edges 包含角色关系信息。

  • password_history 保留以前选择的密码,以便限制密码重用。见 第 8.2.15 节,“密码管理”

服务器在启动时将授权表的内容读取到内存中。您可以通过发出 FLUSH PRIVILEGES 语句或执行 mysqladmin flush-privilegesmysqladmin reload 命令来重新加载授权表。授权表的更改将如 第 8.2.13 节,“何时生效的权限更改” 所示。

当您修改账户时,验证您的更改是否产生了预期的效果是一个好主意。要检查某个账户的权限,请使用 SHOW GRANTS 语句。例如,要确定用户名和主机名值为 bobpc84.example.com 的账户的权限,请使用以下语句:

SHOW GRANTS FOR 'bob'@'pc84.example.com';

要显示账户的非权限属性,请使用 SHOW CREATE USER

SHOW CREATE USER 'bob'@'pc84.example.com';

用户和 db 授权表

服务器在访问控制的第一和第二阶段使用 userdb 表(见 第 8.2 节,“访问控制和账户管理”)。以下是 userdb 表的列。

表 8.4 user 和 db 表列

Table Name user db
Scope columns 主机 主机
用户 Db
用户
Privilege columns Select_priv Select_priv
Insert_priv Insert_priv
Update_priv Update_priv
Delete_priv Delete_priv
Index_priv Index_priv
Alter_priv Alter_priv
Create_priv Create_priv
Drop_priv Drop_priv
Grant_priv Grant_priv
Create_view_priv Create_view_priv
Show_view_priv Show_view_priv
Create_routine_priv Create_routine_priv
Alter_routine_priv Alter_routine_priv
Execute_priv Execute_priv
Trigger_priv Trigger_priv
事件_priv 事件_priv
Create_tmp_table_priv Create_tmp_table_priv
Lock_tables_priv Lock_tables_priv
References_priv References_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
Show_db_priv
Super_priv
Repl_slave_priv
Repl_client_priv
Create_user_priv
Create_tablespace_priv
Create_role_priv
Drop_role_priv
Security columns ssl_type
ssl_cipher
x509_issuer
x509_subject
插件
身份验证字符串
密码已过期
密码最后更改时间
密码生命周期
账户锁定
密码重用历史记录
密码重用时间
密码需要当前
用户属性
Resource control columns 最大查询数
最大更新数
最大连接数
最大用户连接数

The user 表的 plugin身份验证字符串 列存储身份验证插件和凭据信息。

服务器使用 plugin 列中的插件名称来验证连接尝试的账户。

The plugin 列不能为空。启动时和在执行 FLUSH PRIVILEGES 时,服务器检查 user 表行。对于任何空 plugin 列的行,服务器将写入错误日志的警告信息:

[Warning] User entry 'user_name'@'host_name' has an empty plugin
value. The user will be ignored and no one can login with this user
anymore.

要将插件分配给缺少插件的账户,请使用 ALTER USER 语句。

The 密码已过期 列允许 DBA 将账户密码设为过期,并要求用户重置密码。默认 密码已过期 值为 'N',但可以使用 ALTER USER 语句将其设置为 'Y'。在账户密码过期后,在服务器的后续连接中执行的所有操作将导致错误,直到用户发出 ALTER USER 语句以建立新的账户密码。

Note

虽然可以通过将密码重置为当前值来“重置”已过期的密码,但出于良好政策的考虑,最好选择不同的密码。DBA 可以通过建立适当的密码重用策略来强制执行非重用。请参阅 密码重用策略

密码最后更改时间 是一个 TIMESTAMP 列,指示密码最后更改的时间。该值仅对使用 MySQL 内置身份验证插件(mysql_native_password 已弃用,sha256_passwordcaching_sha2_password)的账户非空。对于其他账户,例如使用外部身份验证系统的账户,该值为空。

密码最后更改时间CREATE USERALTER USERSET PASSWORD 语句更新,并由 GRANT 语句创建账户或更改账户密码时更新。

password_lifetime 表示账户密码生命周期,以天为单位。如果密码超过生命周期(根据 password_last_changed 列评估),服务器将在客户端使用该账户连接时认为密码已过期。值 N 大于零意味着密码必须每 N 天更改一次。值为 0 禁用自动密码过期。如果值为 NULL(默认),则应用全局过期策略,如 default_password_lifetime 系统变量所定义。

account_locked 表示账户是否被锁定(见 第 8.2.20 节,“账户锁定”)。

Password_reuse_history 是账户的 PASSWORD HISTORY 选项的值,或者为 NULL,表示默认历史记录。

Password_reuse_time 是账户的 PASSWORD REUSE INTERVAL 选项的值,或者为 NULL,表示默认间隔。

Password_require_current 对应账户的 PASSWORD REQUIRE 选项的值,如下表所示。

表 8.5 允许的 Password_require_current 值

Password_require_current Value Corresponding PASSWORD REQUIRE Option
'Y' PASSWORD REQUIRE CURRENT
'N' PASSWORD REQUIRE CURRENT OPTIONAL
NULL PASSWORD REQUIRE CURRENT DEFAULT

User_attributes 是一个 JSON 格式的列,存储账户属性,而不是存储在其他列中。INFORMATION_SCHEMA 通过 USER_ATTRIBUTES 表公开这些属性。

The User_attributes 列可能包含以下属性:

  • additional_password:二级密码,如果有。见 双密码支持

  • Restrictions:限制列表,如果有。限制是通过部分撤销操作添加的。该属性值是一个数组,其中每个元素都有 DatabaseRestrictions 键,指示受限数据库的名称和适用限制(见 第 8.2.12 节,“权限限制使用部分撤销”)。

  • Password_locking:失败登录跟踪和临时账户锁定的条件,如果有(见 失败登录跟踪和临时账户锁定)。该 Password_locking 属性根据 FAILED_LOGIN_ATTEMPTSPASSWORD_LOCK_TIME 选项的 CREATE USERALTER USER 语句更新。该属性值是一个哈希,具有 failed_login_attemptspassword_lock_time_days 键,指示已指定的选项值。如果键不存在,其值隐式为 0。如果键值隐式或显式为 0,则相应的功能被禁用。

  • multi_factor_authenticationmysql.user 系统表中的行具有 plugin 列,指示身份验证插件。对于单因素身份验证,该插件是唯一的身份验证因素。但是,对于双因素或三因素的多因素身份验证,该插件对应于第一个身份验证因素,但需要存储第二个和第三个因素的附加信息。multi_factor_authentication 属性持有该信息。

    The multi_factor_authentication 值是一个数组,其中每个数组元素是一个哈希,描述身份验证因素使用以下属性:

    • plugin:身份验证插件的名称。

    • authentication_string:身份验证字符串值。

    • passwordless:一个标志,指示用户是否应使用安全令牌作为唯一的身份验证方法,而不使用密码。

    • requires_registration:一个定义用户账户是否注册了安全令牌的标志。

    数组的第一个和第二个元素描述多因素身份验证因素2和3。

如果没有应用属性,则 User_attributesNULL

示例:一个具有辅助密码和部分撤销数据库权限的账户在列值中具有 additional_passwordRestrictions 属性:

mysql> SELECT User_attributes FROM mysql.User WHERE User = 'u'\G
*************************** 1. row ***************************
User_attributes: {"Restrictions":
                   [{"Database": "mysql", "Privileges": ["SELECT"]}],
                  "additional_password": "hashed_credentials"}

要确定哪些属性存在,请使用 JSON_KEYS() 函数:

SELECT User, Host, JSON_KEYS(User_attributes)
FROM mysql.user WHERE User_attributes IS NOT NULL;

要提取特定的属性,例如 Restrictions,请执行以下操作:

SELECT User, Host, User_attributes->>'$.Restrictions'
FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';

以下是存储在 multi_factor_authentication 中的信息示例:

{
  "multi_factor_authentication": [
    {
      "plugin": "authentication_ldap_simple",
      "passwordless": 0,
      "authentication_string": "ldap auth string",
      "requires_registration": 0
    },
    {
      "plugin": "authentication_webauthn",
      "passwordless": 0,
      "authentication_string": "",
      "requires_registration": 1
    }
  ]
}

tables_priv 和 columns_priv 授予权表

在访问控制的第二阶段,服务器执行请求验证,以确保每个客户端都具有足够的权限来发出每个请求。在 userdb 授予权表之外,服务器还可能会咨询 tables_privcolumns_priv 表,以便对涉及表的请求进行更细粒度的权限控制。这些表具有以下列。

表 8.6 tables_priv 和 columns_priv 表列

Table Name tables_priv columns_priv
Scope columns 主机 主机
Db Db
User User
Table_name Table_name
Column_name
Privilege columns Table_priv Column_priv
Column_priv
Other columns Timestamp Timestamp
Grantor

TimestampGrantor 列分别设置为当前时间戳和 CURRENT_USER 值,但否则未使用。

procs_priv 授予权表

对于涉及存储例程的请求验证,服务器可能会咨询 procs_priv 表,该表具有以下列。

表 8.7 procs_priv 表列

Table Name procs_priv
作用域列 主机
Db
User
Routine_name
Routine_type
权限列 Proc_priv
其他列 Timestamp
Grantor

Routine_type 列是一个 ENUM 列,具有 'FUNCTION''PROCEDURE' 值,以指示该行引用的例程类型。这使得可以单独授予函数和同名过程的权限。

TimestampGrantor 列未使用。

proxies_priv 授予权表

proxies_priv 表记录代理账户的信息。它具有以下列:

  • 主机, User:代理账户,即具有 PROXY 权限的账户。

  • Proxied_host, Proxied_user:被代理的账户。

  • Grantor, Timestamp:未使用。

  • With_grant:代理账户是否可以授予其他账户PROXY权限。

要使账户能够授予其他账户PROXY权限,它必须在proxies_priv表中有一行,With_grant设置为1,Proxied_hostProxied_user设置为指示授予权限的账户或账户。例如,在MySQL安装期间创建的'root'@'localhost'账户在proxies_priv表中有一行,启用授予PROXY权限给''@'',即所有用户和所有主机。这使得root能够设置代理用户,以及将设置代理用户的权限委托给其他账户。见第8.2.19节,“代理用户”

global_grants 授予权限表

global_grants 表列出了当前分配给用户账户的动态全局权限。该表具有以下列:

  • USER, HOST:授予权限的账户的用户名和主机名。

  • PRIV:权限名称。

  • WITH_GRANT_OPTION:账户是否可以授予该权限给其他账户。

default_roles 授予权限表

default_roles 表列出了默认用户角色。它具有以下列:

  • HOST, USER:应用默认角色的账户或角色。

  • DEFAULT_ROLE_HOST, DEFAULT_ROLE_USER:默认角色。

role_edges 授予权限表

role_edges 表列出了角色子图的边缘。它具有以下列:

  • FROM_HOST, FROM_USER:授予权限的账户。

  • TO_HOST, TO_USER:授予权限的角色。

  • WITH_ADMIN_OPTION:账户是否可以授予该角色给其他账户,并使用WITH ADMIN OPTION撤销该角色。

password_history 授予权限表

password_history 表包含密码更改信息。它具有以下列:

  • Host, User:密码更改的账户。

  • Password_timestamp:密码更改的时间。

  • Password:新密码哈希值。

password_history 表累积了每个账户的足够数量的非空密码,以便MySQL执行密码历史记录长度和重用间隔检查。密码更改尝试时自动修剪超出限制的条目。

Note

空密码不计入密码历史记录,并且可以随时重用。

如果账户被重命名,其条目将被重命名以匹配。如果账户被删除或其身份验证插件被更改,其条目将被删除。

授予权限表范围列属性

授予权限表中的范围列包含字符串。每个列的默认值为空字符串。以下表显示每个列允许的字符数。

表 8.8 授予权限表范围列长度

Column Name Maximum Permitted Characters
Host, Proxied_host 255
User, Proxied_user 32
Db 64
表名 64
列名 64
例程名 64

主机代理主机 值在存储在授权表之前将被转换为小写。

对于访问检查目的,用户代理用户身份验证字符串数据库表名 值的比较是区分大小写的。比较 主机代理主机列名例程名 值是不区分大小写的。

授权表权限列属性

userdb 表中,每个权限在一个单独的列中被声明为 ENUM('N','Y') DEFAULT 'N'。换言之,每个权限可以被禁用或启用,默认情况下是禁用。

tables_privcolumns_privprocs_priv 表中,权限列被声明为 SET 列。这些列中的值可以包含表控制的任何权限组合。只有列值中列出的权限被启用。

表 8.9 set 类型权限列值

Table Name Column Name Possible Set Elements
tables_priv 表权限 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter', 'Create View', 'Show view', 'Trigger'
tables_priv 列权限 'Select', 'Insert', 'Update', 'References'
columns_priv 列权限 'Select', 'Insert', 'Update', 'References'
procs_priv 例程权限 'Execute', 'Alter Routine', 'Grant'

只有 userglobal_grants 表指定了管理权限,如 RELOADSHUTDOWNSYSTEM_VARIABLES_ADMIN。管理操作是对服务器本身的操作,而不是数据库特定的,因此没有理由在其他授权表中列出这些权限。因此,服务器只需要咨询 userglobal_grants 表来确定用户是否可以执行管理操作。

FILE 权限也只在 user 表中指定。它不是管理权限,但用户在服务器主机上的读取或写入文件的能力独立于访问的数据库。

授权表并发

为了允许 MySQL 授权表的并发 DML 和 DDL 操作,读操作以前获取行锁的 MySQL 授权表现在执行为非锁定读取。这些操作包括:

  • SELECT 语句和其他只读语句,它们通过连接列表和子查询从授权表中读取数据,包括 SELECT ... FOR SHARE 语句,使用任何事务隔离级别。

  • DML 操作,它们从授权表中读取数据(通过连接列表或子查询),但不修改它们,使用任何事务隔离级别。

语句不再获取行锁时读取授权表数据,将报告警告,如果使用语句基于复制。

使用 -binlog_format=mixed,DML 操作从授权表中读取数据将被写入二进制日志作为行事件,以使操作安全地用于混合模式复制。

SELECT ... FOR SHARE 语句从授权表中读取数据将报告警告。使用 FOR SHARE 子句,不支持在授权表上的读锁。

使用SERIALIZABLE隔离级别执行的读取授权表数据的DML操作将报告警告。在授权表上,不支持使用SERIALIZABLE隔离级别通常获取的读锁。