MySQL grant之后是否需要flush privileges
在MySQL旧版本的使用上,很多人习惯直接更新mysql.user等表来完成用户的修改密码,修改权限等,最后需要flush privileges来生效。
而使用grant来授权或revoke来收权,是不需要执行flush privileges的。
直接修改系统表的方式之所以需要flush privileges,是改了系统表之后,内存里的权限信息并没有同步更新,所以需要将内存的权限信息flush,然后重新加载磁盘里的最新权限信息。
而grant/revoke,是自动完成更新系统表和重新加载内存权限信息。
虽然grant/revoke不需要flush privileges,但针对已存在的连接,还是有一些不生效的情况。
1.全局权限
全局权限即授权对象是grant … on *.*,例如all privileges,super等。
全局权限对于已存在的会话,只会在登陆之初获取一次权限信息,之后执行的grant和revoke,只对新连接的会话生效,而对已存在会话不生效。
会话1,给test@’%'授予all privileges全局权限
mysql> show grants for test@'%';
+----------------------------------+
| Grants for test@% |
+----------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
+----------------------------------+
1 row in set (0.00 sec)
mysql> show grants for test@'%';
+----------------------------------+
| Grants for test@% |
+----------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
+----------------------------------+
1 row in set (0.00 sec)
mysql> grant all privileges on *.* to test@'%';
Query OK, 0 rows affected (0.00 sec)
会话2使用test登陆,可以查询sam.test表
mysql> select count(*) from test;
+----------+
| count(*) |
+----------+
| 7 |
+----------+
1 row in set (0.00 sec)
会话1将test@’%'的all privileges权限收回
mysql> revoke all privileges on *.* from test@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for test@'%';
+----------------------------------+
| Grants for test@% |
+----------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
+----------------------------------+
1 row in set (0.00 sec)
保持着的会话2仍然可以查询sam.test,说明全局权限并没有对会话2生效,但会话2执行show grants显示自己已经没有all privileges权限了,这也说明show grants是读取最新的权限信息,而不是读取会话自己缓存的权限系信息。
mysql> select count(*) from test;
+----------+
| count(*) |
+----------+
| 7 |
+----------+
1 row in set (0.00 sec)
mysql> show grants;
+----------------------------------+
| Grants for test@% |
+----------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
+----------------------------------+
1 row in set (0.00 sec)
我们再来测试一下all privileges on sam.*的回收效果
会话1授予test@’%'对sam库的all privileges
mysql> grant all privileges on sam.* to test@'%';
Query OK, 0 rows affected (0.01 sec)
会话2可以查询sam.test
mysql> select count(*) from test;
+----------+
| count(*) |
+----------+
| 7 |
+----------+
1 row in set (0.00 sec)
会话1回收test@’%'对sam库的all privileges
mysql> revoke all privileges on sam.* from test@'%';
Query OK, 0 rows affected (0.01 sec)
mysql> show grants for test@'%';
+----------------------------------+
| Grants for test@% |
+----------------------------------+
| GRANT USAGE ON *.* TO 'test'@'%' |
+----------------------------------+
1 row in set (0.00 sec)
会话2失去了对sam.test的查询权限
mysql> use information_schema
Database changed
mysql> use sam
ERROR 1044 (42000): Access denied for user 'test'@'%' to database 'sam'
所以,全局权限是指带有*.*的授权。
2.DB权限
例如上面all privileges on sam.*的回收效果测试,在会话1回收test@’%'对sam库的all privileges以后,如果会话2一开始执行了use sam,且回收权限之后没有切换到其他db下,那么会话2是会一直拥有对sam库的权限的。
3.表权限和列权限
对于表权限和列权限,授权和收权对于已存在的会话都是马上生效的。
但这里注意区分,
select on sam.*是DB权限,
select on sam.test是表权限,
select(id) on sam.test是列权限。