权限
全局权限
全局权限,作用于整个MySQL实例,这些权限信息保存在mysql库的user表里。
赋予权限
最高权限命令:
grant all privileges on *.* to 'user'@'%' with grant option;
grant命令做了两个动作:
- 磁盘上,将mysql.user表里,用户’user’@’%'这一行的所有表示权限的字段的值都修改为‘Y’;
- 内存里,从数组acl_users中找到这个用户对应的对象,将access值(权限位)修改为二进制的“全1”
在这个grant命令执行完成后,如果有新的客户端使用用户名ua登录成功,MySQL会为新连接维护一个线程对象,然后从acl_users数组里查到这个用户的权限,并将权限值拷贝到这个线程对象中。之后在这个连接中执行的语句,所有关于全局权限的判断,都直接使用线程对象内部保存的权限位。
收回权限
如果要回收上面的grant语句赋予的权限,你可以使用下面这条命令:
revoke all privileges on *.* from 'user'@'%';
全局权限的权限信息在线程对象中,revoke操作影响不到当前的线程对象。
db权限
赋予
命令:
grant all privileges on db1.* to 'ua'@'%' with grant option;
每次需要判断一个用户对一个数据库读写权限的时候,都需要遍历一次acl_dbs数组,根据user、host和db找到匹配的对象,然后根据对象的权限位来判断。
grant修改db权限的时候,是同时对磁盘和内存生效的。
回收
db权限的acl_dbs是一个全局数组,所有线程判断db权限都用这个数组,这样revoke操作马上就会影响到当前会话的权限判断。
表权限&列权限
表权限定义存放在表mysql.tables_priv中,列权限定义存放在表mysql.columns_priv中。这两类权限,组合起来存放在内存的hash结构column_priv_hash中。
grant all privileges on db1.t1 to 'ua'@'%' with grant option;
GRANT SELECT(id), INSERT (id,a) ON mydb.mytbl TO 'ua'@'%' with grant option;
两个权限每次grant的时候都会修改数据表,也会同步修改内存中的hash结构。 因此,对这两类权限的操作,也会马上影响到已经存在的连接。
flush privileges
flush privileges命令会清空acl_users数组,然后从mysql.user表中读取数据重新加载,重新构造一个acl_users数组。也就是说,以数据表中的数据为准,会将全局权限内存数组重新加载一遍。
正常情况下,grant命令之后,没有必要跟着执行flush privileges命令。 只有当数据表中的权限数据跟内存中的权限数据不一致的时候,flush privileges语句可以用来重建内存数据,达到一致状态。这种不一致往往是由不规范的操作导致的,比如直接用DML语句操作系统权限表
不规范的写法
grant super on *.* to 'ua'@'%' identified by 'pa';
加了identified by ‘密码’, 语句的逻辑里面除了赋权外,还包含了:
- 如果用户’ua’@’%'不存在,就创建这个用户,密码是pa;
- 如果用户ua已经存在,就将密码修改成pa。