Skip to content

42 | grant之后要跟着flush privileges吗? #55

@git-zjx

Description

@git-zjx

MySQL中的用户权限

创建用户

create user 'ua'@'%' identified by 'pa';

这个语句用于创建一个用户 'ua'@'%',密码是 pa,在 MySQL 中,用户名(user) + 地址(host) 才表示一个用户,因此 ua@ip1 和 ua@ip2 表示两个不同用户

这个语句做了两个动作:

  1. 磁盘里,向 mysql.user 表里插入一行,由于没有指定权限,所以这行数据上所有表示权限的字段的值都是 N
  2. 内存里,向数组 acl_users 里插入一个 acl_user 对象,这个对象的 access 字段值为 0

MySQL 中,用户权限是有不同范围的,分别是全局权限、db 权限、表权限和列权限

全局权限

全局权限作用于整个 MySQL 实例,这些权限信息保存在 mysql 库的 user 表里

grant all privileges on *.* to 'ua'@'%' with grant option;

这个 grant 命令做了两个动作:

  1. 磁盘里,将 mysql.user 表里,用户 'ua'@'%' 这一行的所有表示权限的字段的值都修改为 Y
  2. 内存里,从数组 acl_users 中找到这个用户对应的对象,将 access 值(权限位)修改为二进制的全1

grant 命令执行完成后即时生效,接下来创建的连接会使用新的权限,但不影响已经存在的连接

db 权限

基于库的权限记录保存在 mysql.db 表中,在内存里则保存在数组 acl_dbs 中

grant all privileges on db1.* to 'ua'@'%' with grant option;

这个 grant 命令做了两个动作:

  1. 磁盘里,向 mysql.db 表中插入一行记录,所有权限位字段设置为 Y
  2. 内存里,增加一个对象到数组 acl_dbs 中,这个对象的权限位为全1

acl_dbs 是一个全局数组,所有线程判断 db 权限都用这个数组,但如果当前会话已经处于某一个 db 里面,之前 use 这个库的时候拿到的权限就会保存在会话变量中

表权限和列权限

基于表的权限记录保存在 mysql.tables_priv 中,基于列的权限记录保存在 mysql.columns_priv 中。这两类权限组合起来存放在内存的 hash 结构 column_priv_hash 中

create table db1.t1(id int, a int);

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;

和 db 权限类型,这两个权限每次 grant 的时候都会修改数据表并修改内存中的 hash 结构,会影响到已经存在的连接

取消权限

revoke all privileges on *.* from 'ua'@'%';
revoke all privileges on db1.* from 'ua'@'%';

操作与 grant 命令相反

flush privileges 使用场景

当数据表中的权限数据跟内存中的权限数据不一致的时候,flush privileges 语句可以重建内存数据,达到一致状态

出现不一致的原因:

  1. 直接使用 DML 语句操作系统权限表
  2. 赋予全局权限时,因为每个连接都会有一个线程对象都维护一个 acl_users 数组,所以已有连接可能会存在不一致的情况

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions