文章目录
- [第一章 用户与权限体系概述](#第一章 用户与权限体系概述)
- [第二章 用户创建与属性配置](#第二章 用户创建与属性配置)
-
- [2.1 创建用户的基本语法](#2.1 创建用户的基本语法)
-
- [2.1.1 密码加密机制](#2.1.1 密码加密机制)
- [2.2 用户信息存储的本质](#2.2 用户信息存储的本质)
- [第三章 密码管理与安全策略](#第三章 密码管理与安全策略)
-
- [3.1 修改用户密码](#3.1 修改用户密码)
-
- [3.1.1 `SET PASSWORD` 与 `PASSWORD()` 函数的兼容性](#3.1.1
SET PASSWORD与PASSWORD()函数的兼容性) - [3.1.2 MySQL 8.0 及之后版本的正确做法](#3.1.2 MySQL 8.0 及之后版本的正确做法)
- [3.1.1 `SET PASSWORD` 与 `PASSWORD()` 函数的兼容性](#3.1.1
- [第四章 权限分配与回收](#第四章 权限分配与回收)
-
- [4.1 给用户授权(GRANT)](#4.1 给用户授权(GRANT))
- [4.2 查看用户权限](#4.2 查看用户权限)
- [4.3 刷新权限(FLUSH PRIVILEGES)](#4.3 刷新权限(FLUSH PRIVILEGES))
- [4.4 回收用户权限(REVOKE)](#4.4 回收用户权限(REVOKE))
- [第五章 用户删除与管理](#第五章 用户删除与管理)
-
- [5.1 删除用户(DROP USER)](#5.1 删除用户(DROP USER))
-
- [5.1.1 关于 `%` 通配符的说明](#5.1.1 关于
%通配符的说明)
- [5.1.1 关于 `%` 通配符的说明](#5.1.1 关于
- [第六章 常见问题排查与特殊场景](#第六章 常见问题排查与特殊场景)
-
- [6.1 MySQL 配置参数 `skip-grant-tables` 的影响](#6.1 MySQL 配置参数
skip-grant-tables的影响)
- [6.1 MySQL 配置参数 `skip-grant-tables` 的影响](#6.1 MySQL 配置参数
- [第七章 最佳实践总结](#第七章 最佳实践总结)
第一章 用户与权限体系概述
在生产环境中,直接使用 root 用户操作数据库是一项高风险行为。root 用户拥有无限权限,一旦密码泄露或发生误操作,后果不堪设想。因此,建立精细化的用户管理与权限控制体系,是数据库安全的第一道防线。
MySQL 将所有用户信息和权限数据存储在系统数据库
mysql的user表中。
这张表是 MySQL 权限体系的核心,我们可以通过查询它来了解当前所有用户的基本情况。
sql
-- 切换到 mysql 数据库
USE mysql;
-- 查看用户的基本信息(主机、用户名、密码密文)
SELECT host, user, authentication_string FROM user;
查询结果中的关键字段含义如下:
host:表示该用户允许从哪个主机或 IP 登录。localhost代表仅限本机登录,%则是通配符,代表允许从任意主机远程登录。user:登录用户名。authentication_string(/ɔːˌθentɪˈkeɪʃən strɪŋ/) :用户密码经过加密算法处理后的密文字符串。
需要注意的是,mysql.user 表中的权限是全局级别 的。一个用户能否连接服务器,取决于 host、user 和 password 这三者的组合是否匹配。
第二章 用户创建与属性配置
2.1 创建用户的基本语法
创建用户的标准 SQL 语句是 CREATE USER。
sql
CREATE USER '用户名'@'登录主机/主机名' IDENTIFIED BY '密码';
'用户名'@'登录主机/主机名':这是 MySQL 中用户的唯一标识。MySQL 通过"用户名 + 主机名"的组合来区分不同的账户。如果省略主机名部分,则默认为'%',即允许从任何主机登录。IDENTIFIED BY '密码':用于设置该用户的登录密码。
2.1.1 密码加密机制
这是一个非常关键的问题。在 CREATE USER 语句中,我们直接输入的是明文密码 。这个明文密码在存入 mysql.user 表的 authentication_string 字段之前,会由 MySQL 服务器自动进行加密处理。
开发者不需要也不应该手动调用加密函数。MySQL 会根据当前配置的认证插件(如 mysql_native_password 或 caching_sha2_password)自动完成加密。
案例:创建一个新用户
sql
-- 创建一个名为 'app_user',只允许从本机 (localhost) 登录的用户
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'StrongP@ssw0rd!';
-- 创建一个名为 'remote_user',允许从任何主机 (%) 登录的用户
CREATE USER 'remote_user'@'%' IDENTIFIED BY 'AnotherP@ss!';
-- 查看创建后的用户信息(密码已被自动加密)
SELECT host, user, authentication_string FROM user WHERE user IN ('app_user', 'remote_user');
安全提示: 不要轻易添加一个可以从任意地方登录('%')的用户,这会显著增加被攻击的风险。
2.2 用户信息存储的本质
"创建用户是不是就是在 mysql.user 表里进行 CURD 操作?"这个问题,触及了用户管理的本质。
答案是:从最终效果上看,是的。但官方强烈推荐使用专门的 SQL 语句(如 CREATE USER),而不是直接对 mysql.user 表进行 INSERT、UPDATE 或 DELETE 操作。
直接操作系统表风险极高,容易破坏数据完整性或导致权限系统混乱。使用 CREATE USER、DROP USER 等专用 DDL 语句是更安全、更规范的做法。
第三章 密码管理与安全策略
3.1 修改用户密码
修改用户密码有两种常见场景:
1. 用户修改自己的密码
在 MySQL 5.7 及更早版本中,可以使用:
sql
SET PASSWORD = PASSWORD('新密码');
2. 管理员(如 root)修改指定用户的密码
同样,在旧版本中可以使用:
sql
SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码');
3.1.1 SET PASSWORD 与 PASSWORD() 函数的兼容性
"改密码语法在新版本里面是否已失效?"
结论是:在 MySQL 8.0 中,PASSWORD() 函数已被移除,SET PASSWORD ... = PASSWORD('...') 的语法已不再可用。
- MySQL 5.7 :
PASSWORD()函数已被标记为废弃(deprecated),但仍可使用。 - MySQL 8.0 :
PASSWORD()函数被彻底移除,上述语法会直接报错。
3.1.2 MySQL 8.0 及之后版本的正确做法
在 MySQL 8.0 中,修改密码统一使用 ALTER USER 用户@主机 IDENTIFIED BY 新密码,普通用户修改自己的密码和管理员修改其他用户密码语法相同,只是权限不同。
sql
-- 修改自己的密码
ALTER USER '用户名'@'主机名' IDENTIFIED BY '新密码';
-- root 用户修改指定用户的密码
ALTER USER 'app_user'@'localhost' IDENTIFIED BY 'NewStrongP@ss!';
SET PASSWORD 语句本身在 MySQL 8.0 中并未被完全废弃,但其用法已经改变。现在,SET PASSWORD 在内部会被重写为 ALTER USER 语句。为了更好的兼容性和清晰性,直接使用 ALTER USER 是官方推荐的最佳实践。
第四章 权限分配与回收
4.1 给用户授权(GRANT)
新创建的用户默认没有任何权限。我们需要使用 GRANT 语句来赋予其操作数据库的权限。
授权语法:
sql
GRANT 权限列表 ON 库.对象名 TO '用户名'@'登录位置' [IDENTIFIED BY '密码'];
权限列表:要授予的权限,如SELECT,INSERT,UPDATE,DELETE等,多个权限用逗号分隔 。使用ALL [PRIVILEGES]表示授予该对象上的所有权限。库.对象名:权限作用范围。*.*:代表本系统中的所有数据库及其所有对象。库名.*:代表指定数据库中的所有对象(表、视图、存储过程等)。库名.表名:代表指定数据库中的特定表。
[IDENTIFIED BY '密码']:可选。如果用户存在,则在授权的同时修改其密码;如果用户不存在,则创建该用户。

案例:授予查询权限
sql
-- 使用 root 账号
-- 授予 'app_user'@'localhost' 对 test 数据库下所有表的 SELECT 权限
GRANT SELECT ON test.* TO 'app_user'@'localhost';
-- 授予 'app_user'@'localhost' 对 test 数据库的 SELECT, INSERT, UPDATE 权限
GRANT SELECT, INSERT, UPDATE ON test.* TO 'app_user'@'localhost';
-- 授予 'remote_user'@'%' 对 test 数据库的所有权限
GRANT ALL PRIVILEGES ON test.* TO 'remote_user'@'%';
授权后,用户需要重新连接才能使部分权限生效,或者执行权限刷新操作。
4.2 查看用户权限
可以使用 SHOW GRANTS 命令查看特定用户的权限。
sql
-- 查看 'app_user'@'localhost' 的权限
SHOW GRANTS FOR 'app_user'@'localhost';
4.3 刷新权限(FLUSH PRIVILEGES)

截图中的 flush privileges; 命令,其核心作用是 重新从 mysql 系统库的权限表中加载最新的用户信息和权限设置到内存中。
何时需要执行?
- 正常情况下 :使用
GRANT、REVOKE、CREATE USER、DROP USER等专用 SQL 语句修改权限后,MySQL 会自动感知变更并更新内存中的缓存,通常不需要 手动执行FLUSH PRIVILEGES。 - 特殊情况下 :如果通过
INSERT、UPDATE、DELETE等语句直接修改了mysql.user等系统权限表 ,那么内存中的权限缓存并不会自动更新。此时,必须执行FLUSH PRIVILEGES来强制服务器重新加载权限表,使更改生效。
4.4 回收用户权限(REVOKE)
REVOKE 语句用于回收已授予用户的权限。
回收权限语法:
sql
REVOKE 权限列表 ON 库.对象名 FROM '用户名'@'登录位置';
案例:回收权限
sql
-- 使用 root 账号
-- 回收 'app_user'@'localhost' 对 test 数据库的所有权限
REVOKE ALL ON test.* FROM 'app_user'@'localhost';
第五章 用户删除与管理
5.1 删除用户(DROP USER)
DROP USER 语句用于移除一个或多个 MySQL 账户。
删除用户语法:
sql
DROP USER '用户名'@'主机名';
5.1.1 关于 % 通配符的说明
删除用户时必须指定完整主机名的情况。MySQL 中,'whb' 和 'whb'@'%' 是两个完全不同的账户。
如果执行 DROP USER 'whb';,MySQL 会默认将主机名部分视为 '%',即尝试删除 'whb'@'%' 这个用户。如果该用户不存在,就会报错 ERROR 1396 (HY000)。要删除 'whb'@'localhost',必须精确指定完整名称。
sql
-- 错误示例:尝试删除 'whb',但默认匹配的是 'whb'@'%'
DROP USER 'whb'; -- 如果 'whb'@'%' 不存在则报错
-- 正确示例:精确指定主机名
DROP USER 'whb'@'localhost';
第六章 常见问题排查与特殊场景
6.1 MySQL 配置参数 skip-grant-tables 的影响
"MySQL 配置文件选项会让 netstat -nltp 查不到",这个现象与 skip-grant-tables 参数有关。
- 功能 :当 MySQL 服务器以
--skip-grant-tables选项启动时,它将不读取权限表,也不实施任何访问控制。这意味着任何用户都可以无密码登录并拥有所有权限,通常用于紧急情况下的密码重置。 - 副作用 :启用该参数后,MySQL 为了安全考虑,会默认开启
skip-networking,即禁用所有 TCP/IP 网络连接 。服务器仅允许本地 socket 连接,因此使用netstat -nltp命令将无法看到 MySQL 服务监听在 3306 端口上。 - 解决方法 :在完成紧急操作后,务必从配置文件(如
/etc/my.cnf)中移除或注释掉skip-grant-tables这一行,然后重启 MySQL 服务,恢复正常权限检查和网络监听。
第七章 最佳实践总结
- 最小权限原则 :仅授予用户完成其工作所必需的最小权限集。避免随意授予
ALL PRIVILEGES。 - 限制登录主机 :尽量指定具体的 IP 或主机名,避免使用
'%'通配符,以减少攻击面。 - 使用专用 DDL 语句 :始终使用
CREATE USER、GRANT、REVOKE、DROP USER等专用语句管理用户和权限,不要直接修改mysql.user表。 - 关注版本差异 :注意 MySQL 不同版本间的语法差异,尤其是在 8.0 版本中,应使用
ALTER USER来修改密码。 - 谨慎使用维护参数 :
skip-grant-tables仅用于紧急故障恢复,切忌在生产环境中长期开启。