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


8.2.3 授权表

`mysql` 系统数据库包含多个授权表,用于存储用户账户和他们拥有的权限信息。这一节描述这些表。关于系统数据库中其他表的信息,请见第7.3节,“The mysql System Schema”

本节讨论授权表的 underlying 结构和服务器在与客户端交互时如何使用它们的内容。然而,通常您不直接修改授权表。修改是通过使用帐户管理语句,如CREATE USERGRANTREVOKE来设置账户和控制每个账户可用的权限的。见第15.7.1节,“Account Management Statements”。当您使用这些语句执行帐户操作时,服务器将在您的 behalf 修改授权表。

Note

不建议使用语句,如INSERTUPDATEDELETE直接修改授权表。服务器可以忽略由于这些修改而变得不正确的行。

对任何修改授权表的操作,服务器都会检查该表是否具有预期的结构,如果不是,则产生错误。要将表更新到预期的结构,请执行 MySQL 升级程序。见第 3 章, 升级 MySQL

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

关于静态和动态全局权限的差异,见静态 versus 动态权限。)

MySQL 8.4中,授权表使用InnoDB存储引擎,并且是事务性的。之前的 MySQL 8.4,授权表使用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范围列确定是否拒绝或允许 incoming 连接。对于允许的连接,用户表中的任何权限都表示用户的静态全局权限。用户表中的任何权限都适用于服务器上的所有数据库。

    Caution

    由于任何静态全局权限都是对所有数据库的权限,因此任何静态全局权限都使得用户可以使用SHOW DATABASES语句或通过检查INFORMATION_SCHEMASCHEMATA表来查看所有数据库名称,except those that have been restricted at the database level by partial revokes。

  • 用户账户的当前动态全局权限分配列表在global_ grants表中。对于每一行,范围列确定拥有该权限的用户是谁,该权限列中的权限名称。

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

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

  • 存储过程(存储程序和函数)相关的procs_priv表。对某个存储程序或函数授予的权限仅适用于单个程序或函数。

  • proxies_priv表指示哪些用户可以作为其他用户的代理,并且一个用户是否可以将PROXY权限授予给其他用户。

  • default_rolesrole_edges表包含角色关系的信息。

  • password_history表保留了之前选择的密码,以便限制密码重复使用。请参阅第8.2.15节,“密码管理”

服务器在启动时将grant表的内容读入内存中。你可以通过执行FLUSH PRIVILEGES语句或执行mysqladmin flush-privilegesmysqladmin reload命令来重新加载grant表。grant表的更改将在第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 授权表

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

Table 8.4 user and db Table Columns

Table Name user db
Scope columns Host Host
User Db
User
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
Event_priv Event_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
plugin
authentication_string
password_expired
password_last_changed
password_lifetime
account_locked
Password_reuse_history
Password_reuse_time
Password_require_current
User_attributes
Resource control columns max_questions
max_updates
max_connections
max_user_connections

用户表中的pluginauthentication_string列存储身份验证插件和凭证信息。

服务器使用用户账户行的plugin列中指定的插件来.authenticate连接尝试。

plugin列不能为空。启动时和在执行FLUSH PRIVILEGES语句时,服务器检查用户表行。如果存在空的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语句。

password_expired列允许DBA过期账户密码,并要求用户重置密码。默认的password_expired值是'N'ALTER USER语句将其设置为'Y'。在账户密码过期后,用户在服务器的所有操作都将导致错误,直到用户使用ALTER USER语句来建立新的账户密码。

Note

虽然可以通过将密码设置为当前值来““重置””过期的密码,但作为良好的政策,建议选择不同的密码。DBA可以通过建立适当的密码重用策略来强制不重复使用密码。请参阅Password Reuse Policy

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

password_last_changedCREATE USERALTER USERSET PASSWORD语句和GRANT语句更新,用于创建账户或更改账户密码。

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

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

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 密码要求当前默认

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

User_attributes 列可能包含以下属性:

  • additional_password: 如果存在,secondary 密码。请参阅Dual Password Support

  • Restrictions: 如果存在,限制列表。限制是通过部分撤销操作添加的。该属性值是一个数组,每个元素都有DatabaseRestrictions 键,表示受限数据库的名称和对其的适用限制(请参阅Section 8.2.12, “Privilege Restriction Using Partial Revokes”)。

  • 密码锁定: 失败登录跟踪和临时账户锁定的条件,如果有(见失败登录跟踪和临时账户锁定)。密码锁定属性根据CREATE USERALTER USER语句的FAILED_LOGIN_ATTEMPTSPASSWORD_LOCK_TIME选项进行更新。该属性值是一个哈希,其中包含failed_login_attemptspassword_lock_time_days键,表示为该账户指定的选项的值。如果一个键缺失,它的值被隐式设置为0。如果一个键值被隐式或显式设置为0,该对应的能力将被禁用。

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

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

    • 插件: 认证插件的名称。

    • 认证字符串: 认证字符串值。

    • 无密码: 表示用户是否需要使用安全令牌作为唯一身份验证方法的标志。

    • 需要注册: 定义用户账户是否已注册安全令牌的标志。

    数组的前两个元素描述了多因素身份验证因子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授权表外,服务器还可能会 consulted tables_privcolumns_priv 表,以处理涉及表的请求。后者表提供了更细粒度的权限控制,用于表和列级别。它们具有以下表格所示的列。

表8.6:tables_priv 和 columns_priv 表列

Table Name tables_priv columns_priv
Scope columns Host Host
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表,该表具有以下表格所示的列。

Table 8.7 procs_priv Table Columns

Table Name procs_priv
Scope columns Host
Db
User
Routine_name
Routine_type
Privilege columns Proc_priv
Other columns Timestamp
Grantor

Routine_type 列是一个 ENUM 列,其值为 'FUNCTION''PROCEDURE',用于指示该行所指例程的类型。此列允许分别为具有相同名称的函数和过程授予权限。

TimestampGrantor 列未使用。

proxies_priv 表格记录了代理帐户的信息。它包含以下列:

  • Host, User: 代理帐户;即拥有被代理帐户的 PROXY 权限的帐户。

  • Proxied_主机, Proxied_用户: 代理账户。

  • 授权人, 时间戳: 未使用。

  • With_授权: 是否可以将PROXY特权授予其他账户。

为了使一个账户能够授予PROXY特权给其他账户,它必须在proxies_priv表中有一个行,With_授权设置为1,并且Proxied_主机Proxied_用户设置为指示可以授予特权的账户或账户列表。例如,MySQL安装时创建的'root'@'localhost'账户在proxies_priv表中有一个行,使得授予PROXY特权给''@'',即所有用户和所有主机。这使得root可以设置代理账户,同时也可以将授权权委托给其他账户,以便它们可以设置代理账户。请参阅第8.2.19节,“Proxy Users”

The global_授权 表列出了当前分配给用户帐户的动态全局权限。这个表有这些列:

  • 用户, 主机: 被授予特权的帐户的用户名和主机名。

  • PRIV: 权限名称。

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

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

  • HOST, USER: 权限或角色的账户或角色。

  • DEFAULT_ROLE_HOST, DEFAULT_ROLE_USER: 默认角色。

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

  • FROM_HOST, FROM_USER: 授予角色的账户。

  • TO_HOST, TO_USER: 授予给账户的角色。

  • WITH_ADMIN_OPTION: 账户是否可以使用WITH ADMIN OPTION授予角色的权限和撤销权限。

密码历史表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
Table_name 64
Column_name 64
Routine_name 64

HostProxied_host 值将在存储到授权表时转换为小写。

为了访问检查目的,UserProxied_userauthentication_stringDbTable_name值的比较是区分大小写的。对HostProxied_hostColumn_nameRoutine_name值的比较不是区分大小写的。

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

tables_privcolumns_privprocs_priv表中,特权列被声明为SET列。这些列中的值可以包含由该表控制的所有特权的任意组合。只有列值中列出的特权是启用的。

Table 8.9 Set-Type Privilege Column Values

Table Name Column Name Possible Set Elements
tables_priv Table_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter', 'Create View', 'Show view', 'Trigger'
tables_priv Column_priv 'Select', 'Insert', 'Update', 'References'
columns_priv Column_priv 'Select', 'Insert', 'Update', 'References'
procs_priv Proc_priv 'Execute', 'Alter Routine', 'Grant'

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

FILE权限也只在user表中指定。它不是管理权限,而是用户对服务器主机的文件读取或写入能力,这与访问的数据库无关。

为了允许MySQL授权表上的并发DML和DDL操作,之前在MySQL授权表上获取行锁的读操作将被执行为非锁定读操作。对MySQL授权表进行非锁定读操作的操作包括:

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

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

从授权表中读取数据的语句,如果在使用 statement-基于复制时执行,将报告警告,不会获取行锁。

使用 binlog_ format=mixed 时,读取授权表数据的 DML 操作将被写入二进制日志中,以使操作安全地支持混合模式复制。

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

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