服务器接受连接后,进入访问控制的第 2 阶段。对于您通过连接发出的每个请求,服务器都会确定您要执行的操作,然后检查您的权限是否足够。这就是授权表中的特权列发挥作用的地方。这些权限可以来自user
、
db
、tables_priv
、
columns_priv
或procs_priv
表中的任何一个。(您可能会发现参考
第 6.2.3 节“授权表”很有帮助,其中列出了每个授权表中的列。)
该user
表授予全局权限。帐户的
user
表行指示在全局基础上应用的帐户权限,无论默认数据库是什么。例如,如果user
表授予您DELETE
权限,您可以从服务器主机上任何数据库中的任何表中删除行。明智的做法是只将表中的权限授予
user
需要它们的人,例如数据库管理员。对于其他用户,将user
表中的所有权限保留为'N'
并仅授予更特定级别的权限(对于特定数据库、表、列或例程)。
该db
表授予特定于数据库的权限。此表的范围列中的值可以采用以下形式:
服务器将db
表读入内存,并在读取表的同时进行排序
user
。db
服务器根据Host
、
Db
和User
scope 列对表进行排序
。与user
表格一样,排序将最具体的值放在最前面,最不具体的值放在最后,当服务器查找匹配行时,它会使用它找到的第一个匹配项。
、和表授予特定于表tables_priv
、
特定于列和特定于例程的权限。这些表的范围列中的值可以采用以下形式:
columns_priv
procs_priv
通配符
%
和_
可以在Host
列中使用。这些与使用运算符执行的模式匹配操作具有相同的含义LIKE
。一个
'%'
或空白Host
值表示“任何主机。”、
Db
、Table_name
和Column_name
列Routine_name
不能包含通配符或为空。
服务器根据、
和列对tables_priv
、
columns_priv
和表进行
排序。这类似于表排序,但更简单,因为只有列可以包含通配符。
procs_priv
Host
Db
User
db
Host
服务器使用排序后的表来验证它收到的每个请求。对于需要管理权限(例如SHUTDOWN
或
RELOAD
)的请求,服务器仅检查
user
表行,因为这是唯一指定管理权限的表。如果该行允许请求的操作,则服务器授予访问权限,否则拒绝访问。例如,如果你想执行mysqladmin shutdown但你的user
表行没有授予SHUTDOWN
你权限,服务器甚至不检查
db
表就拒绝访问。(后一个表没有
Shutdown_priv
列,所以不需要检查。)
对于与数据库相关的请求(INSERT
、
UPDATE
等),服务器首先检查
user
表行中用户的全局权限。如果该行允许请求的操作,则授予访问权限。如果表中的全局权限user
不足,则服务器从表中确定用户的数据库特定权限
db
:
服务器在表中查找、和列
db
的匹配项。Host
Db
User
Host
和 列User
与连接用户的主机名和 MySQL 用户名相匹配。该
Db
列与用户要访问的数据库相匹配。如果没有行
Host
和User
,则访问被拒绝。
在确定
db
表行授予的特定于数据库的权限后,服务器将它们添加到表授予的全局权限user
中。如果结果允许请求的操作,则访问被授予。否则,服务器依次检查用户在tables_priv
和
columns_priv
表中的表和列权限,将这些权限添加到用户权限中,并根据结果允许或拒绝访问。对于存储例程操作,服务器使用
procs_priv
表而不是
tables_priv
and
columns_priv
。
用布尔术语表示,前面关于如何计算用户权限的描述可以总结如下:
global privileges
OR database privileges
OR table privileges
OR column privileges
OR routine privileges
可能不清楚为什么,如果最初发现全局权限不足以执行请求的操作,服务器会在稍后将这些权限添加到数据库、表和列权限中。原因是一个请求可能需要不止一种类型的特权。例如,如果您执行一条
INSERT INTO ...
SELECT
语句,您需要
INSERT
和
SELECT
权限。您的权限可能是user
表行授予一个全局权限,而db
表行授予其他专门针对相关数据库。在这种情况下,您拥有执行请求所需的权限,但服务器无法单独从您的全局权限或数据库权限中分辨出来。它必须根据组合的权限做出访问控制决策。