-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
MySQL中的用户权限
创建用户
create user 'ua'@'%' identified by 'pa';
这个语句用于创建一个用户 'ua'@'%'
,密码是 pa
,在 MySQL 中,用户名(user) + 地址(host) 才表示一个用户,因此 ua@ip1 和 ua@ip2 表示两个不同用户
这个语句做了两个动作:
- 磁盘里,向 mysql.user 表里插入一行,由于没有指定权限,所以这行数据上所有表示权限的字段的值都是 N
- 内存里,向数组 acl_users 里插入一个 acl_user 对象,这个对象的 access 字段值为 0
MySQL 中,用户权限是有不同范围的,分别是全局权限、db 权限、表权限和列权限
全局权限
全局权限作用于整个 MySQL 实例,这些权限信息保存在 mysql 库的 user 表里
grant all privileges on *.* to 'ua'@'%' with grant option;
这个 grant 命令做了两个动作:
- 磁盘里,将 mysql.user 表里,用户
'ua'@'%'
这一行的所有表示权限的字段的值都修改为 Y - 内存里,从数组 acl_users 中找到这个用户对应的对象,将 access 值(权限位)修改为二进制的全1
grant 命令执行完成后即时生效,接下来创建的连接会使用新的权限,但不影响已经存在的连接
db 权限
基于库的权限记录保存在 mysql.db 表中,在内存里则保存在数组 acl_dbs 中
grant all privileges on db1.* to 'ua'@'%' with grant option;
这个 grant 命令做了两个动作:
- 磁盘里,向 mysql.db 表中插入一行记录,所有权限位字段设置为 Y
- 内存里,增加一个对象到数组 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 语句可以重建内存数据,达到一致状态
出现不一致的原因:
- 直接使用 DML 语句操作系统权限表
- 赋予全局权限时,因为每个连接都会有一个线程对象都维护一个 acl_users 数组,所以已有连接可能会存在不一致的情况