微信搜索“coder-home”或扫一扫下面的二维码,关注公众号,第一时间了解更多干货分享,还有各类视频教程资源。扫描它,带走我
需求背景
我们平时在给用户授权grant
语句执行后,都习惯性的执行一个命令flush privileges;
,但是我发现有时候不执行这个命令,授权语句执行之后,权限验证也是OK的,但是有时候发现不执行这个flush privileges;
命令,权限认证还不能通过。
那么到底什么情况下需要执行flsh privileges;
?什么情况下不需要执行这个命令呢?
创建用户
当我们创建用户的时候,为了安全起见,我们会在用户名后面增加一个host的限制,标识该用户通过指定的密码,只能通过该IP地址段才可以登录MySQL。
创建用户,语句如下所示:
create user 'user1'@'172.19.%' identified by '123456';
上面的示例是创建了一个用户,名称为'user1'@'172.19.%'
,可以通过172.19.
网段,使用123456
密码来登录MySQL。
如果用户使用不在172.19.
网段,通过这个密码是不能登录MySQL的。言外之意:'user1'@'ip1'
和'uesr1'@'ip2'
是两个不同的用户,我们不能单纯的靠用户名来确认用户,需要把IP地址也纳入进来。
上述语句执行成功后,MySQL会做两件事情:
- 会在mysql.user表中增加一条记录。记录内容如下所示:
- 在MySQL在内存中维护的一个数组变量:
acl_users
,在这个变量中插入了一个元素,就是我新增加的用户。但此时这个数组中记录的用户的权限也是全部为N
,表示这个新增加的用户没有任何范围权限。
给用户授权
前面我们创建了用户,下面我们给这个用户授予访问权限,语句如下所示:
grant all on *.* to 'user1'@'172.19.%';
上述语句执行完成后,MySQL也是做了两件事情:
- 更新了mysql.user表中的这个用户的权限列表,更新后的数据如下:
这个用户的权限如下,从下图中可以看出,该用户用于所有的权限,也就是我们给授予的*.*
的权限。
但是除了一个项Grant_priv
的值为N
,表示该用户不能把自己当前所持有的权限再次赋予其他任何用户,只能自己拥*.*
有这些权限。而如果在我们的授权语句后面追加上with grant option
关键字之后,Grant_priv
的值也会变成Y
,表示这个用户可以把当前自己持有的权限,在赋予其他用户。生产环境将不建议给授权的用户增加with grant option
选项。
- 更新了MySQL内存中数组
acl_users
的中值,把这个用户对应的权限都跟改为Y
,表示该用户拥有了我们赋予它的权限。
授权并创建用户
MySQL中支持可以不先创建用户而直接进行授权,在授权的时候,自己创建用户。也就是说可以把create语句和grant语句合并在一起,组从一个不一样的grant语句。
如下所示,下面的语句是创建一个用户:'user1'@'172.19.%'
,并且给这个用户授予*.*
的权限,同时设置这个用户的密码为123456
。
grant all on *.* to 'user1'@'172.19.%' identified by '123456';
验证登录
用户创建完成,权限也配置好了,现在我们还没有执行flush privileges;
命令。尝试用用户user1@'172.19.%'
来登录,登录的时候,要确保你的登录的时候使用的网段为172.19
,验证结果如下:
我们发现我们并没有执行flush privileges;
命令的前提下,直接使用这个用户登录,就可以登录成功了。
这是为什么?
因为我们在创建用户和为用户授权的时候,MySQL除了维护mysql.user
表中的数据,还维护了内存中的acl_users
数组。在内存中也更新了对应的用户和权限信息。所以我们可以直接使用新创建的用户名和密码来登录。
收回授权
现在我们把用户的权限给收回,收回后不执行flush privileges;
命令,看下用户是否还可以登录MySQL。收回授权的语句如下:
revoke all privileges on *.* from 'user1'@'172.19.%';
验证用户是否还可以访问所有的数据库,这里在验证的时候,需要退出原先的登录,重新建立连接才可以。因为MySQL数据库中,对于全局权限的修改(也就是*.*
的权限的修改),都是对新连接才生效,已经存在的连接不受影响的。
我们退出上一次的登录,重新登录后的结果如下:看到只能看到information-schema
了,其他都看不到了。这是因为所有的用户,在没有任何权限的时候,默认都可以看到information_schema
这个数据库。此时我们在收回用户授权后并没有执行flush privileges;
命令。
删除用户
现在我们将用户删除掉,看下是否还可以登录MySQL数据库。删除用户的语句如下:
drop user 'user1'@'172.19.%';
验证是否可以登录,在验证的时候,同样我们需要先退出上一次的登录重新建立连接。验证后的结果如下,我们发现已经不能登录MySQL数据库了。此时我们在删除用户后并没有执行flush privileges;
命令。
总结
通过上面的创建用户、给用户授权、收回授权、删除用户的操作,我们可以发现在不执行flush privileges;
命令的时候,这些操作都是生效了。也就是说,此时我们是没有必要执行flush privileges;
命令的。
那么什么情况下才需要执行flush privileges;
命令呢?
当我们不是通过create user
、grant
、revoke
、drop
命令来操作用户和权限,而是通过update
语句直接去修改了mysql.user
表中的数据的时候,此时我们需要执行flush privileges;
命令。
此时我们也应该知道flush privileges;
命令的作用了,它的作用就是清空MySQL内存中acl_users
数组的数据内容,重新从mysql.user
表中加载用户的权限信息。
而当我们直接修改了mysql.user
表中的内容的时候,MySQL内存中的acl_users
数据信息是没有被更新的,所以此时我们想让我们对mysql.user
表的修改直接生效,就需要手动的去更新acl_users
数组的信息,而这个更新内存权限信息的操作,也就是通过flush privileges;
命令来实现的。
所以,在我们日常的维护MySQL的时候,还是使用create user
、grant
、revoke
、drop
命令去维护用户相关的信息。尽量避免直接使用update
命令去修改mysql.user
表中的信息。
微信搜索“coder-home”或扫一扫下面的二维码,关注公众号,第一时间了解更多干货分享,还有各类视频教程资源。扫描它,带走我