文章目录
- [1. 用户](#1. 用户)
-
- [1.1 用户信息](#1.1 用户信息)
- [1.2 创建用户](#1.2 创建用户)
- [1.3 删除用户](#1.3 删除用户)
- [1.4 修改用户密码](#1.4 修改用户密码)
- [2. 数据库的权限](#2. 数据库的权限)
-
- [2.1 给用户授权](#2.1 给用户授权)
- [2.2 回收权限](#2.2 回收权限)
如果我们只能使用 root 用户,这样存在安全隐患。这时,就需要使用 MySQL 的用户管理。
如下所示:

张三只能操纵 mytest 这个库,李四只能操纵 msg 这个库。如果给他们 root 账户,那他们就可以操纵所有的库,风险太大。
1. 用户
1.1 用户信息
MySQL 中的用户,都存储在系统数据库 mysql 的 user 表中:
sql
select host,user,authentication_string from user;
结果如下:

字段解释:
host:表示这个用户可以从哪个主机登陆,如果是 localhost,表示只能从本机登陆;user:用户名;authentication_string:用户密码通过 password 函数进行哈希加密后的;*_priv:用户拥有的权限。
1.2 创建用户
语法:
sql
create user '用户名'@'登陆主机/ip' identified by '密码';
案例:创建 edison 用户
sql
create user 'edison'@'localhost' identified by '123456';
注意,当你执行上述语句以后,如果像下面这样报错了:

核心原因是 MySQL 启动时加载了 --skip-grant-tables 参数(跳过权限表校验),此时权限系统被禁用,无法执行创建用户、授权等和权限相关的操作。
解决思路是:给 root 设置密码后,再关闭 skip-grant-tables 参数恢复正常权限体系,步骤如下(全程用 root 操作系统权限):
- 给 root 设置密码(MySQL 5.7 及以下)
sql
# 切换到 mysql 库(权限表所在库)
use mysql;
# 更新 root 密码(密码改成你想要的,比如 123456)
update user set authentication_string = password('123456') where user = 'root' and host = 'localhost';
# 刷新权限
flush privileges;
结果如下:

- 编辑 MySQL 配置文件:
vim /etc/my.cnf,注释掉skip-grant-tables

-
重启 MySQL 服务:
systemctl restart mysqld -
验证登录:此时用刚设置的密码登录 root,即可正常操作。
-
但是当你想切换某个数据库时,发现又报错了

这是因为 ERROR 1820 (HY000) 是 MySQL 的「密码过期 / 未初始化强制重置」机制触发了 ------ 即使你刚设置了 root 密码,MySQL 仍要求显式执行 ALTER USER 完成密码重置流程。
- 先强制重置 root 密码(解决 1820 报错),这里密码必须设置为:大小写 + 字符组合。
sql
SET PASSWORD = PASSWORD('QAZwsxedc123456.');
- 然后刷新权限并退出
sql
# 使密码生效
flush privileges;
# 退出当前 MySQL 会话
exit;
- 此时,重启 MySQL 服务,再登录即可,切换某个数据库就不会再出现问题了

- 开始执行创建
edison用户的语句(这里密码必须设置为:大小写 + 字符组合。)
sql
# 创建用户
create user 'edison'@'localhost' identified by 'QAZwsxedc123456.';
# 查看用户表
select user,host,authentication_string from user;
# 刷新权限
flush privileges;
结果如下:

此时便可以使用 edison 进行登陆啦

注意:因为 MySQL 本身的认证等级比较高,一些简单的密码无法设置,会爆出如下报错
sql
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
1.3 删除用户
语法:
sql
drop user '用户名'@'主机名'
- 尝试删除
如果直接给个用户名,不能删除,它默认是 %,表示所有地方可以登陆的用户
sql
mysql> drop user edison;
ERROR 1396 (HY000): Operation DROP USER failed for 'edison'@'%'
必须添加 @localhost 才能删除(相当于告诉 MySQL 删除本主机上的 edison 用户)
sql
drop user 'edison'@'localhost';
结果如下:

那么,我们还可以创建一个运行远程登录的用户
sql
# 创建用户
create user 'edison'@'%' identified by 'QAZwsxedc123456.';
# 刷新权限
flush privileges;
结果如下:

此时,切换到 Windows 命令窗口,执行下面的命令,即可登录成功:
sql
mysql -uedison -h[服务器IP地址] -P 3306 -p
1.4 修改用户密码
语法:
- 自己改自己密码
sql
set password=password('新的密码');
- root 用户修改指定用户的密码
sql
set password for '用户名'@'主机名'=password('新的密码');
- 以 root 用户的身份修改
edison用户的密码
sql
# 修改密码
set password for 'edison'@'%'=password('Qwer123456.');
# 刷新权限
flush privileges;
结果如下:

当然,还可以使用 update 对 edison 用户密码做修改
sql
# 修改密码
update user set authentication_string=password('QAZwsxedc123456.') where user='edison';
# 刷新权限
flush privileges;
结果如下:

其实本质上就是对 user 表进行 CURD 操作,只不过 MySQL 专门设置了一套语法罢了。
2. 数据库的权限
下面是 MySQL 数据库提供的权限列表:
以下是重新整理后的表格(保持原内容不变):
| 权限 | 列 | 上下文 |
|---|---|---|
| CREATE | Create_priv | 数据库、表或索引 |
| DROP | Drop_priv | 数据库或表 |
| GRANT OPTION | Grant_priv | 数据库、表或保存的程序 |
| REFERENCES | References_priv | 数据库或表 |
| ALTER | Alter_priv | 表 |
| DELETE | Delete_priv | 表 |
| INDEX | Index_priv | 表 |
| INSERT | Insert_priv | 表 |
| SELECT | Select_priv | 表 |
| UPDATE | Update_priv | 表 |
| CREATE VIEW | Create_view_priv | 视图 |
| SHOW VIEW | Show_view_priv | 视图 |
| ALTER ROUTINE | Alter_routine_priv | 保存的程序 |
| CREATE ROUTINE | Create_routine_priv | 保存的程序 |
| EXECUTE | Execute_priv | 保存的程序 |
| FILE | File_priv | 服务器主机上的文件访问 |
| CREATE TEMPORARY TABLES | Create_tmp_table_priv | 服务器管理 |
| LOCK TABLES | Lock_tables_priv | 服务器管理 |
| CREATE USER | Create_user_priv | 服务器管理 |
| PROCESS | Process_priv | 服务器管理 |
| RELOAD | Reload_priv | 服务器管理 |
| REPLICATION CLIENT | Repl_client_priv | 服务器管理 |
| REPLICATION SLAVE | Repl_slave_priv | 服务器管理 |
| SHOW DATABASES | Show_db_priv | 服务器管理 |
| SHUTDOWN | Shutdown_priv | 服务器管理 |
| SUPER | Super_priv | 服务器管理 |
2.1 给用户授权
先创建一个 Tom 用户,允许远程登录
sql
# 创建用户
create user 'Tom'@'%' identified by 'QAZwsxedc123456.';
# 刷新权限
flush privileges;
结果如下:

此时,创建的用户没有任何权限,那么需要给用户授权。
语法:
sql
grant 权限列表 on 库.对象名 to '用户名'@'登陆位置' [identified by '密码']
说明:
- 权限列表,多个权限用逗号分开
sql
grant select on ...
grant select, delete, create on ....
# 表示赋予该用户在该对象上的所有权限
grant all [privileges] on ...
-
*.*:代表本系统中的所有数据库的所有对象(表,视图,存储过程等); -
库.*:表示某个数据库中的所有数据对象(表,视图,存储过程等); -
identified by可选,如果用户存在,赋予权限的同时修改密码,如果该用户不存在,就是创建用户。
案例如下:
分别以 root 和 Tom 的身份登录数据库:

然后在 root 用户下新创建一个 rootDB 的数据库:
sql
create database if not exists rootDB;
此时,在 Tom 用户下,是看不到 rootDB 这个库的。

然后以 root 用户的身份,在 rootDB 库中创建 user 表,并插入两条数据:
sql
# 使用数据库
use rootDB;
# 建表
create table user(
id int primary key,
name varchar(20) not null
);
# 插入数据
insert into user values (1, '张三');
insert into user values (2, '李四');
结果如下:

此时,我们在 root 用户下,给用户 Tom 授予 rootDB 数据库下 user 表的所有权限
sql
grant all on rootDB.user to 'Tom'@'%';
然后 Tom 用户就可以使用 rootDB 数据库,并可以查看 user 表了

此时,我们在 root 用户中,可以查看赋予了 Tom 用户哪些权限?
sql
show grants for 'Tom'@'%';
结果如下:

并且,Tom 用户可以对 user 表进行插入数据:

2.2 回收权限
语法:
sql
revoke 权限列表 on 库.对象名 from '用户名'@'登陆位置';
现在我想不给 Tom 用户【插入】权限,如下所示:
sql
# 回收insert权限
revoke insert on rootDB.user from 'Tom'@'%';
结果如下:

此时 Tom 用户不能再对 user 表进行【insert / 插入】操作,但是其他权限还在:

还可以回收 Tom 用户的所有权限
sql
revoke all on rootDB.user from 'Tom'@'%';
结果如下:

此时,Tom 用户已经看不到 rootDB 数据库以及该库中的 user 表了

那么可以给 Tom 用户一个【只读】权限
sql
grant select on rootDB.user to 'Tom'@'%';
结果如下:

此时 Tom 用户就可以看到 rootDB 数据库以及库当中 user 表的内容了

最后记得回收掉 Tom 用户的【只读】权限,然后删除该用户
sql
# 回收读权限
revoke select on rootDB.user from 'Tom'@'%';
# 删除Tom用户
drop user 'Tom'@'%';
# 刷新权限
flush privileges;
结果如下:
