Time:2019-8-15 21.42 Site:深圳科兴科学院 Author: strivewang
摘要
- 第一部分是介绍Mysql创建用户以及相应的权限介绍。
- 第二部分细节介绍了Mysql不同维度的权限控制
- 第三部分讲解了权限控制
1. Mysql创建用户
第一条语句的逻辑是创建一个用户’user'@'%’,密码是 password。用户名是user, host是%,表示所有的ip
create user 'ua'@'%' identified by 'password';
第二条语句的逻辑是创建一个用户’user'@'192.168.0.1’,密码是 password。用户名是user, host是192.168.0.1,表示所有的ip
create user 'ua'@'192.168.0.1' identified by 'password';
这条命令做了两个动作:
- 磁盘上,往 mysql.user 表里插入一行,由于没有指定权限,所以这行数据上表示所有的权限字段都是 N。
- 内存上,往数组 acl_users 里插入一个 acl_user 对象,这个对象的access 字段值为 0 。
图一就是用户 ua 的状态图

2. 全局权限
2.1 授予全局权限
全局权限:作用于整个 MySQL 实例,这些权限信息保存在 Mysql 库的 user 表中,如果需要给一个用户赋予最高权限,就是:
grant all privileges on *.* to 'user'@'%' with grant option;
这个 grant 命令做了两个动作:
- 磁盘上,将 mysql.user 表里,用户’user@’%' 这一行所有表示权限的字段修改为 ‘Y'
- 内存中,从数组acl_users 中找到这个用户的对象,将acess值(权限位)修改为二进制的 "全1".
2.2 取消用户全局权限:
revoke all privileges on *.* from 'user'@'%';
这个 grant 命令做了两个动作:
- 磁盘上,将 mysql.user 表里,用户’user@’%' 这一行所有表示权限的字段修改为 ‘N'
- 内存中,从数组acl_users 中找到这个用户的对象,将acess值(权限位)修改为二进制的 "全0".
3. DB权限
除了全局权限,Mysql也支持库、表、列等权限的定义。
3.1 授予用户指定库权限
#授予ua用户db1库所有的权限
grant all privileges on db1.* to 'ua'@'%' with grant option;
基于库的权限记录保存在 mysql.db 中,在内存里则保存在数组acl_dbs中,这个grant命令做了如下两个操作:
- 磁盘上,往mysql.db 表中插入一行记录,所有权限字段设置为 “Y”。
- 内存里, 增加一个对象到数组acl_dbs 中,这个对象的权限位设为 “全1”。
下图就是当前用户 ua 在 DB表中的的权限状态:

grant 修改 db 权限的时候,对磁盘和内存是同时生效的。
4. 表权限、列权限
除了全局权限、DB级别的权限之外,Mysql还支持更细粒度的表权限和列权限。其中表权限定义在mysql.table_priv,列权限定义在mysql.columns_priv中。这两种权限,组合起来存放在内存的Hash结构column_priv_hash中。
这两种权限的命令如下:
create table db1.t1(id int, a int);
# 赋予用户ua 库db1的t1表权限
grant all privileges on db1.t1 to 'ua'@'%' with grant option;
# 赋予用户ua 读id、插入id,a列的权限
GRANT SELECT(id), INSERT (id,a) ON mydb.mytbl TO 'ua'@'%' with grant option;
和 db 权限类似,表、列的权限每次 grant 的时候都会修改数据表,也会同步修改内存中的 hash 结构。因此这两个操作会马上影响已存在的链接。
5. flush privileges 问题
==既然 grant 每次执行完就是即时生效, 那为什么有时候需要执行 flush privileges 呢?==
-
flush privileges 命令会清空 acl_users 数组,然后从 mysql.user 中重新读取数据加载到内存当中,重新构造一个 acl_users 数组。换句话说就是以数据表中的数据为准,将内存中的权限数组重新加载一边。
-
其实每次 grant 之后是不需要执行 flush privileges 的,只有当内存中的数据权限和磁盘表中的数据不同的时候,才需要执行 flush privileges 。如果我们规范的使用 grant、revoke,就不需要执行 flush privileges 。
因此,正常情况下,执行完 grant 之后,就不需要执行 flush privileges 。
5.1 flush privileges 使用场景
从上面分析得出,使用 flush privileges 的场景,无非就是 内存中权限数据跟磁盘数据表权限数据不一致,需要使用 flush privileges 来同步内存中的权限数据。
这种数据不一致,往往都是不规则的命令造成的,比如直接操作 mysql.user 表等等。 通过下面的表来解释一下不规范的操作导致的需要使用 flush privileges 来使权限数据一致。

所以,直接操作数据库系统表是不规范的操作,就会导致内存中的权限数据和磁盘中的数据不一致。
还有更奇怪的现象如下图4:

总结一下Mysql 中权限的作用以及在内存中和磁盘中存在的位置,如图5:

本人的学习公众号,欢迎大家骚扰讨论
