Mysql的权限问题以及flush privileges:
Mysql的权限分为以下四种:
1.全局权限
eg:grant all privileges on *.* to 'test'@'%' with grant option;
revoke all privileges on *.* from 'test'@'%';
2.db权限
eg:grant all privileges on testdb.* to 'test'@'%' with grant option;
revoke all privileges on testdb.* from 'test'@'%';
3.表权限
eg:grant all privileges on testdb.test0701 to 'test'@'%' with grant option;
4.列权限
eg:grant select(id), insert(id,a) on testdb.test0702 to 'test'@'%' with grant option;
每种权限的信息都会在磁盘和内存中存储,具体的存储位置为:
1.全局权限
磁盘:表mysql.user
内存:数组acl_user
2.db权限
磁盘:表mysql.db
内存:数组acl_dbs
3.表权限
磁盘:表mysql.tables_priv
内存:和列权限组成的hash结构column_priv_hash
4.列权限
磁盘:表mysql.columns_priv
内存:和表权限组成的hash结构column_priv_hash
每种权限的修改策略和作用范围:
1.全局权限
策略:已存在的连接不生效,新建立连接立即生效
范围:当前线程
2.db权限
策略:所有连接立即生效
范围:全局
(注:这里面有个特殊情况,如果会话在持有某个db的权限时进入了该db,那么会话在执行use xxx时拿到的权限就会保存在会话变量中,即使之后别的会话revoke了权限,也不会影响到该会话,在切换出该db之前该会话会一直持有权限)
3.表权限
策略:所有连接立即生效
范围:全局
4.列权限
策略:所有连接立即生效
范围:全局
关于flush privileges操作:
对于全局权限,flush privileges操作会清空acl_user数组,然后从mysql.user表中读取数据重新构造一个acl_user数组,也就是以数据表中数据为准,将内存数组重新加载一遍
对于db权限、表权限和列权限,Mysql也是做了这样的处理。
所以说如果内存中的权限数据和磁盘表中的数据一致的话,flush privileges其实是可以不用做的。
而对于正常的grant/revoke/create user等操作,内存和磁盘中的数据都是同步更新的,所以正常的grant/revoke操作后是不需要flush privileges的。
flush privileges的使用场景:
当我们直接用DML语句修改系统权限表(mysql.user、mysql.db、mysql.tables_priv、mysql.columns_priv)时,内存中的权限数组是不会同步更新的,此时我们就需要flush privileges来更新内存权限数据了。
eg:delete from mysql.user where user='test0701';
(内容总结自极客时间 丁奇大神的Mysql实战45讲之 42 | grant之后要跟着flush privileges吗?
专栏内容很精彩,推荐给大家哟~
传送门:https://time.geekbang.org/column/intro/139)