乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

用户管理

导学

数据库安全的第一道防线是用户管理。MySQL 5.7 提供了完善的用户认证和账号管理机制,理解它才能避免"所有人用 root"的安全灾难。

定义

用户(User):MySQL 中由用户名和主机名共同标识的账号,格式为 '用户名'@'主机名'。用户的认证信息(密码插件、密码哈希)存储在 mysql.user 系统表中。

创建用户

基础创建

第一步:查看当前所有用户

SELECT user, host, plugin, password_expired
FROM mysql.user
ORDER BY user, host;

当前数据状态(mysql.user 部分字段):

userhostpluginpassword_expired
rootlocalhostmysql_native_passwordN
mysql.sessionlocalhostmysql_native_passwordN
mysql.syslocalhostmysql_native_passwordN

第二步:创建基础用户

-- 创建只能从本机连接的用户
CREATE USER 'app_user'@'localhost'
IDENTIFIED BY 'StrongPassword123!';

-- 创建只能从指定网段连接的用户
CREATE USER 'app_user'@'192.168.1.%'
IDENTIFIED BY 'StrongPassword123!';

-- 创建可以从任何主机连接的用户(最不安全,生产环境慎用)
CREATE USER 'app_user'@'%'
IDENTIFIED BY 'StrongPassword123!';

第三步:确认用户创建成功

SELECT user, host, plugin, password_expired
FROM mysql.user
WHERE user LIKE 'app_user'
ORDER BY user, host;

操作后的数据状态:

userhostpluginpassword_expired
app_user%mysql_native_passwordN
app_user192.168.1.%mysql_native_passwordN
app_userlocalhostmysql_native_passwordN

结果解读:

  • 同一个用户名 app_user 搭配不同的主机名,形成了三个完全独立的账号。
  • 'app_user'@'localhost' 只能从数据库本机连接。
  • 'app_user'@'192.168.1.%' 只能从 192.168.1.x 网段连接,常用于内网应用服务器。
  • 'app_user'@'%' 允许从任何 IP 连接,安全风险最高,生产环境应避免对高权限账号使用。
  • MySQL 5.7 默认使用 mysql_native_password 认证插件。

高级创建(指定插件和过期策略)

第一步:创建带密码过期策略的用户

CREATE USER 'admin_user'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'AdminPass456!'
PASSWORD EXPIRE INTERVAL 90 DAY;

第二步:确认创建结果

SELECT user, host, plugin, password_expired, password_lifetime
FROM mysql.user
WHERE user = 'admin_user';

操作后的数据状态:

userhostpluginpassword_expiredpassword_lifetime
admin_userlocalhostmysql_native_passwordN90

结果解读:

  • IDENTIFIED WITH mysql_native_password 显式指定认证插件。
  • PASSWORD EXPIRE INTERVAL 90 DAY 设置密码 90 天后过期,过期后用户登录时必须修改密码。
  • password_lifetime = 90 表示该用户密码的生命周期为 90 天。

修改用户

修改密码

第一步:查看修改前的用户状态

SELECT user, host, password_expired, password_last_changed
FROM mysql.user
WHERE user = 'app_user' AND host = 'localhost';

当前数据状态:

userhostpassword_expiredpassword_last_changed
app_userlocalhostN2026-06-10 15:00:00

第二步:修改密码

ALTER USER 'app_user'@'localhost'
IDENTIFIED BY 'NewPassword456!';

第三步:确认密码已修改

SELECT user, host, password_last_changed
FROM mysql.user
WHERE user = 'app_user' AND host = 'localhost';

操作后的数据状态:

userhostpassword_last_changed
app_userlocalhost2026-06-10 15:05:00

结果解读:

  • password_last_changed 字段更新为当前时间,表明密码已被修改。
  • 修改密码后,已建立的连接不会断开,但新连接需要使用新密码。

强制密码过期

第一步:设置密码过期

ALTER USER 'app_user'@'localhost' PASSWORD EXPIRE;

第二步:确认密码已过期

SELECT user, host, password_expired
FROM mysql.user
WHERE user = 'app_user' AND host = 'localhost';

操作后的数据状态:

userhostpassword_expired
app_userlocalhostY

第三步:模拟过期用户登录

当 'app_user'@'localhost' 尝试连接时:

mysql -u app_user -p
Enter password: ************

执行任何查询:

SHOW DATABASES;

结果:

ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

第四步:用户重置密码

ALTER USER USER() IDENTIFIED BY 'ResetPassword789!';

第五步:确认密码状态恢复

SELECT user, host, password_expired
FROM mysql.user
WHERE user = 'app_user' AND host = 'localhost';

操作后的数据状态:

userhostpassword_expired
app_userlocalhostN

结果解读:

  • password_expired = Y 表示用户密码已过期,下次登录后必须修改密码才能执行任何操作。
  • 这常用于安全策略:首次创建用户、定期强制更换密码、或怀疑密码泄露时。
  • 用户登录后执行 ALTER USER USER() IDENTIFIED BY '新密码' 即可解除过期状态。

锁定和解锁用户

第一步:锁定用户

ALTER USER 'app_user'@'localhost' ACCOUNT LOCK;

第二步:确认用户已锁定

SELECT user, host, account_locked
FROM mysql.user
WHERE user = 'app_user' AND host = 'localhost';

操作后的数据状态:

userhostaccount_locked
app_userlocalhostY

第三步:模拟锁定用户登录

mysql -u app_user -p
Enter password: ************

结果:

ERROR 3118 (HY000): Access denied for user 'app_user'@'localhost'. Account is locked.

第四步:解锁用户

ALTER USER 'app_user'@'localhost' ACCOUNT UNLOCK;

第五步:确认用户已解锁

SELECT user, host, account_locked
FROM mysql.user
WHERE user = 'app_user' AND host = 'localhost';

操作后的数据状态:

userhostaccount_locked
app_userlocalhostN

结果解读:

  • ACCOUNT LOCK 可以立即阻止用户登录,无需修改密码或删除用户。
  • 适用于临时停用账号(如员工离职交接期间、安全事件调查期间)。
  • ACCOUNT UNLOCK 恢复账号正常使用,之前设置的密码和权限均保留。

删除用户

第一步:确认要删除的用户存在

SELECT user, host FROM mysql.user WHERE user = 'app_user' ORDER BY host;

当前数据状态:

userhost
app_user%
app_user192.168.1.%
app_userlocalhost

第二步:删除指定用户

DROP USER 'app_user'@'localhost';

第三步:确认用户已删除

SELECT user, host FROM mysql.user WHERE user = 'app_user' ORDER BY host;

操作后的数据状态:

userhost
app_user%
app_user192.168.1.%

结果解读:

  • 'app_user'@'localhost' 已被删除,该用户在所有权限表(mysql.user、mysql.db、mysql.tables_priv 等)中的记录均被清理。
  • 必须使用完整的 '用户名'@'主机名' 格式删除,不能只写 DROP USER 'app_user',否则会报错。
  • 警告:绝对不要使用 DELETE FROM mysql.user WHERE user = 'xxx' 删除用户,这会留下权限表中的残留记录,导致权限混乱。

完整流程示例:创建最小权限的应用用户

场景:为应用系统创建专用数据库用户

第一步:建立应用数据库和表

-- 创建应用数据库
CREATE DATABASE IF NOT EXISTS app_db CHARACTER SET utf8mb4;
USE app_db;

-- 创建员工表
CREATE TABLE employees (
    emp_id INT AUTO_INCREMENT PRIMARY KEY,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
);

-- 插入测试数据
INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

当前数据状态(employees 表):

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

第二步:创建应用专用用户

CREATE USER 'app_user'@'10.0.0.%'
IDENTIFIED BY 'AppPass2024!';

第三步:授予最小权限

GRANT SELECT, INSERT, UPDATE ON app_db.*
TO 'app_user'@'10.0.0.%';

第四步:验证权限生效

-- 查看用户权限
SHOW GRANTS FOR 'app_user'@'10.0.0.%';

权限验证结果:

Grants for app_user@10.0.0.%
GRANT USAGE ON . TO 'app_user'@'10.0.0.%'
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'10.0.0.%'

第五步:以应用用户身份验证操作

使用 'app_user'@'10.0.0.%' 连接数据库:

-- 验证 SELECT 权限(成功)
USE app_db;
SELECT * FROM employees;

结果:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL
-- 验证 INSERT 权限(成功)
INSERT INTO employees (emp_name, dept, score)
VALUES ('小崔', '技术部', 90);
-- 验证 UPDATE 权限(成功)
UPDATE employees SET score = score - 5 WHERE emp_id = 1;
-- 验证 DELETE 权限(失败,未授权)
DELETE FROM employees WHERE emp_id = 2;

结果:

ERROR 1142 (42000): DELETE command denied to user 'app_user'@'10.0.0.%' for table 'employees'
-- 验证 DROP 权限(失败,未授权)
DROP TABLE employees;

结果:

ERROR 1142 (42000): DROP command denied to user 'app_user'@'10.0.0.%' for table 'employees'

第六步:查看操作后的数据

SELECT * FROM employees;

操作后的数据状态(employees 表):

emp_idemp_namedeptscore
1大翔技术部95
2白歌技术部NULL
3小崔技术部90

结果解读:

  • app_user 用户成功执行了 SELECT(查询)、INSERT(新增员工)、UPDATE(分数调整)。
  • DELETE 和 DROP 操作被拒绝,因为未授予这些权限。
  • 这体现了最小权限原则:应用用户只需要完成业务所需的权限,多余的权限一律不授予。

第七步:回收权限

-- 回收 INSERT 权限
REVOKE INSERT ON app_db.* FROM 'app_user'@'10.0.0.%';

-- 查看剩余权限
SHOW GRANTS FOR 'app_user'@'10.0.0.%';

回收后的权限状态:

Grants for app_user@10.0.0.%
GRANT USAGE ON . TO 'app_user'@'10.0.0.%'
GRANT SELECT, UPDATE ON app_db.* TO 'app_user'@'10.0.0.%'

第八步:验证回收后的权限

以 'app_user'@'10.0.0.%' 连接数据库:

USE app_db;

-- 尝试 INSERT(失败)
INSERT INTO employees (emp_name, dept, score)
VALUES ('测试', '测试部', 1);

结果:

ERROR 1142 (42000): INSERT command denied to user 'app_user'@'10.0.0.%' for table 'employees'
-- SELECT 仍然可以执行(成功)
SELECT * FROM employees WHERE emp_id = 1;

结果:

emp_idemp_namedeptscore
1大翔技术部95

结果解读:

  • REVOKE 成功回收了 INSERT 权限,但保留了 SELECT 和 UPDATE。
  • USAGE 权限表示用户可以连接数据库,这是所有用户默认拥有的基础权限,无需回收。
  • 权限回收后,已建立的连接可能需要重新连接才能感知权限变化(取决于客户端缓存)。

第九步:清理(删除用户)

DROP USER 'app_user'@'10.0.0.%';

-- 确认已删除
SELECT user, host FROM mysql.user WHERE user = 'app_user';

结果:空集,用户已完全删除。

查看当前用户

-- 查看当前认证用户(MySQL 实际用于权限校验的用户)
SELECT CURRENT_USER();

结果示例:

CURRENT_USER()
root@localhost
-- 查看当前连接用户(包含客户端信息)
SELECT USER();

结果示例:

USER()
root@localhost
-- 查看当前数据库
SELECT DATABASE();

结果示例:

DATABASE()
app_db

结果解读:

  • CURRENT_USER() 返回实际用于权限判断的用户身份。如果使用了代理用户(proxy user),可能与连接用户不同。
  • USER() 返回当前连接的完整用户信息,包括客户端主机名。
  • 当应用程序使用连接池时,这两个函数可以帮助排查权限问题,确认当前操作使用的是哪个账号。

MySQL 5.7 的密码安全增强

特性说明
默认密码验证插件mysql_native_password(5.7 默认),caching_sha2_password(8.0 默认)
密码过期策略可设置密码有效期,强制定期更换
密码强度验证validate_password 插件强制密码复杂度
安装时生成临时密码首次安装后 root 密码写入日志,必须修改后才能使用

查看密码策略:

SHOW VARIABLES LIKE 'validate_password%';

结果示例:

Variable_nameValue
validate_password_check_user_nameON
validate_password_dictionary_file
validate_password_length8
validate_password_mixed_case_count1
validate_password_number_count1
validate_password_policyMEDIUM
validate_password_special_char_count1

结果解读:

  • validate_password_policy = MEDIUM 表示密码必须包含大小写字母、数字和特殊字符。
  • validate_password_length = 8 要求密码最少 8 位。
  • 尝试创建弱密码会被拒绝:
CREATE USER 'weak_user'@'localhost' IDENTIFIED BY '123';

结果:

ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

常见误区

误区正解
用户名相同就是同一个用户'user'@'localhost' 和 'user'@'%' 是完全不同的两个账号。
root 可以从任何主机登录默认只有 'root'@'localhost',远程 root 需额外创建或修改。
删除用户用 DELETE FROM mysql.user应该用 DROP USER,它会同时清理权限表中的相关记录。

面试考点

Q:MySQL 用户由什么组成?

用户名 + 主机名,如 'user'@'localhost'。相同用户名不同主机名是完全不同的账号。

Q:为什么生产环境不能用 root@%?

root 拥有最高权限,从任意主机可登录意味着一旦密码泄露,攻击者可以从任何地方控制数据库。应创建最小权限的专用账号,并限制登录 IP。

Q:MySQL 5.7 安装后 root 密码在哪?

首次安装时,临时 root 密码写入错误日志(mysqld.log),搜索 "A temporary password is generated for root@localhost"。首次登录后必须修改密码。

小结

  • MySQL 用户由用户名@主机名唯一标识
  • 创建用户用 CREATE USER,修改用 ALTER USER,删除用 DROP USER
  • MySQL 5.7 增强了密码安全:过期策略、强度验证、安装时临时密码
  • 生产环境遵循最小权限原则,禁止 root 远程登录
  • 完整流程:创建用户 → 授予最小权限 → 验证权限边界 → 按需回收 → 最终清理

下一章引子:用户创建好了,但没有任何权限。接下来学习如何精确地授予和回收权限。

下一页
权限管理