zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

MySQL 权限

2023-09-14 09:14:49 时间

创建用户 :

  • 用户 : 'ua'@'%',密码 : pa
create user 'ua'@'%' identified by 'pa';

该命令的内部操作 :

  1. 磁盘上,往 mysql.user表里插入一行,而没有指定权限,权限的字段都是 N
  2. 内存里,往数组 acl_users 里插入 acl_user 对象,该对象的 access 为 0

用户在 user 表的状态 :

select * from mysql.user where user = 'ua';

image.png

全局权限

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

用户 ua 给最高权限 :

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

命令的内部操作 :

  1. 磁盘上,将 mysql.user 表里,用户 'ua'@'%' 的所有权限都修改为 'Y'
  2. 内存里,从数组 acl_users 的该用户的 access (权限位) 改为 全1

小结 :

  • grant 会同时更新磁盘和内存 , 之后的新连接会用新权限
  • 对已存在的连接,它的全局权限不受 grant 影响

回收 grant 给的权限 :

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

命令的内部操作 :

  1. 磁盘上,将 mysql.user 表里,用户 'ua'@'%' 的所有权限都改为 N
  2. 内存里,从数组acl_users中找到这个用户对应的对象,将access的值修改为0

db权限

ua 有库 db1 的所有权限 :

  • 库的权限记录保存在 mysql.db表中
  • 还记录在内存的数组 acl_dbs
grant all privileges on db1.* to 'ua'@'%' with grant option;

该命令的内部操作 :

  1. 磁盘上,往 mysql.db 表中插入记录,所有权限都为 Y
  2. 内存里,增加对象到数组 acl_dbs 中,该对象的权限位为 全1

用户 ua 在 db表的状态 :

select * from mysql.db where user = 'ua';

image.png

grant 对已连接 (全局权限 , 基于 db 的权限) 的影响区别 :

  • set global sync_binlogsuper 权限
  • T3 : 用户 ua 的 super 权限 , 通过 revoke 回收
  • T4 : set global 时,权限验证还是通过了。原因 : super 是全局权限,该权限信息在线程对象中,而 revoke 影响不到该线程对象
  • T5 : 去掉 ua 对 db1 库的所有权限
  • T6 : session B 再操作 db1 库的表,就报错。原因 : acl_dbs是全局数组,所有线程都会判断 db 权限,revoke会马上影响到 session B
  • T6 : session C 和 session B 对表 t 的操作是一样的。但 session B 报错,而 session C 能执行成功。原因 : session C 在 T2 时 use db1,拿到该库的权限,只要没切出db1 库,session C 对该库就一直有权限
session Asession Bsession C
T1connect(root, root)
create database db1;
create user 'ua'@'%' identified by 'pa';
grant super on *.* to 'ua'@'%';
grant all privileges on db1.* to 'ua'@'%';
T2connect(ua, pa)
set global sync_binlog =1; (Query OK)
create table db1.t(c int); (Query OK)
connect(ua, pa)
use db1;
T3revoke super on *.* from 'ua'@'%';
T4set global sync_binlog = 1;
alter table db1.t engine=innode; (Query OK)
alter table t engine=innodb; (Query OK)
T5revoke all privileges on db1.* from 'ua'@'%';
T6set global sync_binlog=1; (Query OK)
alter table db1.t engine=innodb; (ALTER command denied)
alter table t engine=innodb; (Query OK)

表/列权限

MySQL 支持表权限和列权限 :

  • 表权限定义在表 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;

flush privileges 会清空 acl_users 数组,并从 mysql.user 表中读取数据重新加载,重新构造 acl_users 数组

  • 当内存的权限数据和磁盘数据表相同时,就不用 flush privileges

flush privileges

当数据表中的权限数据与内存中的权限数据不一致时,用 flush privileges重建内存数据,达到一致状态

DML 操作系统权限表 :

  • T3 : 用 delete 删除用户 ua ,但 T4 还能用 ua 连接成功。原因 : 内存中 acl_users 数组中还有该用户,系统认为用户还存在
  • T5 : 执行 flush 后,内存更新,T6 用 ua 登录时,就会报错
client Aclient B
T1connet(root, root)
create user 'ua'@'%'identified by 'pa';
T2connect(ua, pa) (connect ok)
disconnet
T3delete from mysql.user where user = ‘ua’;
T4connect(ua, pa) (connect ok)
disconnet
T5flush privileges;
T6connect(ua, pa) (Access Denied)

不规范权限操作 :

  • T3 : 直接删除数据表,而内存的数据还存在
  • T4 : 给用户 ua 赋权限失败,因为 mysql.user表中找不到该记录
  • T5 : 重新创建该用户也不行,因为做内存判断时,会认为该用户还存在
client A
T1connect(root, root)
create user 'ua'@'%' identified by 'pa';
T2delete from mysql.user where user = 'ua';
T3grant super on *_.* to _'ua'@'%' with grent option;
ERROR 1133(42000): Can’t find any matching row in the user table
T4create user 'ua'@'%' identified by 'pa';
ERROR 1396 (HY000): Operation CREATE USER failed for ‘ua’@‘%’