外观
MySQL 用户管理
用户管理概述
用户的重要性
MySQL 用户管理是数据库安全的基础,合理的用户管理可以:
- 防止未授权访问
- 限制用户权限范围
- 便于审计和追踪操作
- 提高数据库安全性
- 满足合规要求
MySQL 用户结构
MySQL 用户由两部分组成:
- 用户名:用户的名称
- 主机名/IP:允许用户连接的来源地址,可以是:
- 具体 IP 地址(如
192.168.1.100) - 网段(如
192.168.1.%) - 本地(
localhost或127.0.0.1) - 所有主机(
%,不推荐)
- 具体 IP 地址(如
示例用户:'root'@'localhost'、'app'@'192.168.1.%'
用户创建
CREATE USER 语法
sql
CREATE USER [IF NOT EXISTS] 'username'@'host' [IDENTIFIED BY 'password']
[IDENTIFIED WITH auth_plugin [BY 'password']]
[DEFAULT ROLE role [, role] ...]
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL N DAY]]
[ACCOUNT {LOCK | UNLOCK}];基本用户创建
创建本地用户
sql
-- 创建本地 root 用户
CREATE USER 'root'@'localhost' IDENTIFIED BY 'StrongRootPassword1!';
-- 创建普通本地用户
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'AdminPassword1!';创建远程用户
sql
-- 创建允许从特定 IP 连接的用户
CREATE USER 'app'@'192.168.1.100' IDENTIFIED BY 'AppPassword1!';
-- 创建允许从网段连接的用户
CREATE USER 'app'@'192.168.1.%' IDENTIFIED BY 'AppPassword1!';
-- 创建允许从任何主机连接的用户(不推荐)
CREATE USER 'app'@'%' IDENTIFIED BY 'AppPassword1!';使用不同认证插件
mysql_native_password(传统方式)
sql
CREATE USER 'user1'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Password1!';caching_sha2_password(MySQL 8.0 默认)
sql
CREATE USER 'user2'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'Password2!';无密码用户(不推荐)
sql
CREATE USER 'user3'@'localhost' IDENTIFIED WITH auth_socket; -- 基于操作系统认证设置资源限制
sql
CREATE USER 'app'@'localhost' IDENTIFIED BY 'AppPassword1!'
WITH MAX_QUERIES_PER_HOUR 1000
MAX_UPDATES_PER_HOUR 500
MAX_CONNECTIONS_PER_HOUR 100
MAX_USER_CONNECTIONS 10;设置密码过期策略
sql
-- 密码永不过期
CREATE USER 'user'@'localhost' IDENTIFIED BY 'Password1!' PASSWORD EXPIRE NEVER;
-- 密码 90 天后过期
CREATE USER 'user'@'localhost' IDENTIFIED BY 'Password1!' PASSWORD EXPIRE INTERVAL 90 DAY;
-- 密码立即过期,首次登录需修改
CREATE USER 'user'@'localhost' IDENTIFIED BY 'Password1!' PASSWORD EXPIRE;创建锁定用户
sql
-- 创建锁定用户,需要手动解锁才能使用
CREATE USER 'user'@'localhost' IDENTIFIED BY 'Password1!' ACCOUNT LOCK;用户信息查询
查看所有用户
sql
-- 查看所有用户(MySQL 5.7+)
SELECT user, host, plugin FROM mysql.user;
-- 查看特定用户
SELECT * FROM mysql.user WHERE user = 'app' AND host = 'localhost';查看用户权限
sql
-- 查看用户的全局权限
SHOW GRANTS FOR 'app'@'localhost';
-- 查看用户的数据库级别权限
SHOW GRANTS FOR 'app'@'localhost' USING 'mysql.db';
-- 查看用户的表级别权限
SHOW GRANTS FOR 'app'@'localhost' USING 'mysql.tables_priv';查看用户资源限制
sql
SELECT user, host, max_questions, max_updates, max_connections, max_user_connections FROM mysql.user;查看用户密码策略
sql
SELECT user, host, password_expired, password_last_changed, password_lifetime FROM mysql.user;用户修改
修改用户名和主机
使用 RENAME USER
sql
-- 重命名用户
RENAME USER 'old_user'@'localhost' TO 'new_user'@'localhost';
-- 修改用户主机
RENAME USER 'user'@'192.168.1.100' TO 'user'@'192.168.1.%';使用 UPDATE(不推荐)
sql
-- 不推荐直接修改系统表,可能导致权限问题
UPDATE mysql.user SET user = 'new_user' WHERE user = 'old_user' AND host = 'localhost';
FLUSH PRIVILEGES;修改用户密码
ALTER USER 方式(推荐)
sql
-- 修改用户密码
ALTER USER 'user'@'localhost' IDENTIFIED BY 'NewPassword1!';
-- 修改认证插件和密码
ALTER USER 'user'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'NewPassword1!';SET PASSWORD 方式
sql
SET PASSWORD FOR 'user'@'localhost' = 'NewPassword1!';使用 mysqladmin 工具
bash
mysqladmin -u user -p'oldpassword' password 'newpassword'修改密码过期策略
sql
-- 设置密码永不过期
ALTER USER 'user'@'localhost' PASSWORD EXPIRE NEVER;
-- 设置密码 90 天过期
ALTER USER 'user'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
-- 立即过期密码
ALTER USER 'user'@'localhost' PASSWORD EXPIRE;修改资源限制
sql
-- 修改资源限制
ALTER USER 'app'@'localhost' WITH MAX_QUERIES_PER_HOUR 2000 MAX_UPDATES_PER_HOUR 1000;
-- 移除资源限制
ALTER USER 'app'@'localhost' WITH MAX_QUERIES_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0;锁定和解锁用户
sql
-- 锁定用户
ALTER USER 'user'@'localhost' ACCOUNT LOCK;
-- 解锁用户
ALTER USER 'user'@'localhost' ACCOUNT UNLOCK;修改用户默认角色
sql
-- 设置用户默认角色
ALTER USER 'user'@'localhost' DEFAULT ROLE 'developer', 'readonly';
-- 移除默认角色
ALTER USER 'user'@'localhost' DEFAULT ROLE NONE;用户删除
DROP USER 语法
sql
DROP USER [IF EXISTS] 'username'@'host' [, 'username'@'host'] ...;删除单个用户
sql
-- 删除指定用户
DROP USER 'app'@'192.168.1.%';
-- 删除多个用户
DROP USER 'app1'@'localhost', 'app2'@'localhost';
-- 删除不存在的用户(使用 IF EXISTS 避免错误)
DROP USER IF EXISTS 'nonexistent'@'localhost';注意事项
- 删除用户时会自动移除该用户的所有权限
- 删除用户前应先确认该用户没有正在执行的会话
- 建议使用
IF EXISTS避免因用户不存在导致的错误
MySQL版本差异与用户管理
| 特性 | MySQL 5.6 | MySQL 5.7 | MySQL 8.0 |
|---|---|---|---|
| 默认认证插件 | mysql_native_password | mysql_native_password | caching_sha2_password |
| CREATE USER 语法 | 基本语法 | 增强语法,支持更多选项 | 完整语法,支持角色和资源限制 |
| 密码策略插件 | 需手动安装 | 内置 validate_password | 内置 validate_password,增强功能 |
| 密码过期功能 | 不支持 | 支持 | 支持,增强配置选项 |
| 账户锁定功能 | 不支持 | 支持 | 支持 |
| 资源限制 | 支持 | 支持 | 支持 |
| 角色管理 | 不支持 | 支持 | 增强支持 |
| 密码复杂度验证 | 需手动安装插件 | 内置支持 | 增强支持 |
| 临时表权限 | 有限制 | 增强 | 增强 |
| 撤销权限语法 | REVOKE 基本语法 | REVOKE 增强语法 | REVOKE 完整语法 |
| 权限表结构 | 传统结构 | 新增 role_edges 表 | 增强 role_edges 表 |
用户认证管理
认证插件
MySQL 支持多种认证插件,常用的有:
| 插件名称 | 描述 | 适用场景 |
|---|---|---|
| caching_sha2_password | MySQL 8.0 默认,安全性高 | 推荐使用 |
| mysql_native_password | 传统认证方式 | 兼容性要求高的场景 |
| auth_socket | 基于操作系统用户认证 | 本地管理用户 |
| sha256_password | 基于 SHA-256 认证 | 安全性要求高的场景 |
| pam | 基于 PAM 认证 | 集成外部认证系统 |
切换认证插件
sql
-- 将用户切换到 caching_sha2_password
ALTER USER 'user'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'Password1!';
-- 将用户切换到 mysql_native_password
ALTER USER 'user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Password1!';密码复杂度验证
安装 validate_password 插件
sql
-- 安装密码验证插件
INSTALL PLUGIN validate_password SONAME 'validate_password.so';
-- 查看插件状态
SHOW PLUGINS LIKE 'validate_password';配置密码复杂度
sql
-- 查看密码验证插件配置
SHOW VARIABLES LIKE 'validate_password%';
-- 配置密码复杂度
SET GLOBAL validate_password_policy = 'MEDIUM'; -- 中等复杂度
SET GLOBAL validate_password_length = 8; -- 最小长度 8
SET GLOBAL validate_password_number_count = 1; -- 至少一个数字
SET GLOBAL validate_password_special_char_count = 1; -- 至少一个特殊字符
SET GLOBAL validate_password_mixed_case_count = 1; -- 至少一个大小写用户会话管理
查看用户会话
sql
-- 查看所有活动会话
SHOW PROCESSLIST;
-- 查看特定用户的会话
SELECT * FROM information_schema.processlist WHERE user = 'app';终止用户会话
sql
-- 终止特定会话
KILL [CONNECTION | QUERY] process_id;
-- 示例:终止 ID 为 123 的会话
KILL 123;
-- 终止用户的所有会话
SELECT CONCAT('KILL ', id, ';') FROM information_schema.processlist WHERE user = 'app';
-- 复制结果并执行限制用户会话数
sql
-- 在创建用户时限制会话数
CREATE USER 'app'@'localhost' IDENTIFIED BY 'Password1!' WITH MAX_USER_CONNECTIONS 10;
-- 修改现有用户的会话数限制
ALTER USER 'app'@'localhost' WITH MAX_USER_CONNECTIONS 20;最佳实践
用户命名规范
| 场景 | 命名示例 | 规范说明 |
|---|---|---|
| 管理员 | admin@localhost | 只允许本地连接 |
| 应用用户 | app_name@192.168.1.% | 按应用命名,限制网段 |
| 只读用户 | app_name_read@192.168.1.% | 明确标识只读权限 |
| 监控用户 | monitor@192.168.1.% | 只授予监控所需权限 |
| 备份用户 | backup@192.168.1.100 | 只允许备份服务器连接 |
密码策略
- 使用强密码:包含大小写字母、数字和特殊字符
- 密码长度至少 8 位
- 定期更换密码(90-180 天)
- 不同环境使用不同密码
- 使用密码管理工具
最小权限原则
- 只授予用户所需的最小权限
- 避免使用
GRANT ALL PRIVILEGES ON *.* - 按功能划分用户(读写、只读、管理等)
- 定期审查用户权限
连接限制
- 避免使用
'user'@'%'允许所有主机连接 - 尽量限制为特定 IP 或网段
- 限制用户的并发连接数
- 配置合理的连接超时时间
定期审计
- 定期审查用户列表,删除不必要的用户
- 审计用户权限变更
- 监控用户登录和操作
- 记录和分析异常登录尝试
安全配置
- 禁用匿名用户:删除所有
''@'localhost'或''@'%'匿名用户sqlDELETE FROM mysql.user WHERE user = ''; FLUSH PRIVILEGES; - 移除默认的测试数据库:删除 test 数据库sql
DROP DATABASE IF EXISTS test; DELETE FROM mysql.db WHERE Db = 'test' OR Db LIKE 'test\_%'; FLUSH PRIVILEGES; - 为 root 用户设置强密码:使用复杂密码sql
ALTER USER 'root'@'localhost' IDENTIFIED BY 'StrongRootPassword2024!'; - 限制 root 用户只能本地连接:确保 root 用户只允许本地访问sql
DELETE FROM mysql.user WHERE user = 'root' AND host != 'localhost'; FLUSH PRIVILEGES; - 启用密码过期策略:设置合理的密码过期时间sql
SET GLOBAL default_password_lifetime = 90; -- 90天过期 - 启用连接控制插件:防止暴力破解sql
INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so'; INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so'; SET GLOBAL connection_control_failed_connections_threshold = 3; SET GLOBAL connection_control_min_connection_delay = 1000; SET GLOBAL connection_control_max_connection_delay = 30000; - 禁用不必要的权限表访问:限制普通用户对权限表的访问sql
REVOKE SELECT ON mysql.* FROM 'app_user'@'localhost'; - 启用审计日志:记录用户活动(MySQL 8.0+)sql
INSTALL PLUGIN audit_log SONAME 'audit_log.so'; SET GLOBAL audit_log_policy = 'ALL';
用户管理自动化脚本
创建应用用户脚本
bash
#!/bin/bash
# 创建 MySQL 应用用户脚本
# 配置参数
MYSQL_USER="root"
MYSQL_PASSWORD="RootPassword1!"
APP_NAME="myapp"
APP_PASSWORD="AppPassword1!"
APP_HOST="192.168.1.%"
DB_NAME="myapp_db"
# 日志函数
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1"
}
# 执行 SQL 命令
mysql_exec() {
mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -e "$1"
}
# 主函数
main() {
log "开始创建应用用户: $APP_NAME@$APP_HOST"
# 创建应用用户
mysql_exec "CREATE USER IF NOT EXISTS '$APP_NAME'@'$APP_HOST' IDENTIFIED BY '$APP_PASSWORD' WITH MAX_USER_CONNECTIONS 50;"
if [ $? -eq 0 ]; then
log "用户创建成功"
else
log "用户创建失败"
exit 1
fi
# 授予数据库权限
mysql_exec "GRANT SELECT, INSERT, UPDATE, DELETE ON $DB_NAME.* TO '$APP_NAME'@'$APP_HOST';"
if [ $? -eq 0 ]; then
log "权限授予成功"
else
log "权限授予失败"
exit 1
fi
# 刷新权限
mysql_exec "FLUSH PRIVILEGES;"
log "应用用户创建完成"
}
# 执行脚本
main清理过期用户脚本
bash
#!/bin/bash
# 清理过期 MySQL 用户脚本
# 配置参数
MYSQL_USER="root"
MYSQL_PASSWORD="RootPassword1!"
LOG_FILE="/var/log/mysql/cleanup_users.log"
# 日志函数
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}
# 执行 SQL 命令
mysql_exec() {
mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -e "$1"
}
# 主函数
main() {
log "开始清理过期用户"
# 获取超过 90 天未使用的用户(需要 performance_schema 启用)
EXPIRED_USERS=$(mysql_exec "SELECT user, host FROM mysql.user WHERE user NOT IN ('root', 'mysql.sys', 'mysql.session') AND password_last_changed < DATE_SUB(NOW(), INTERVAL 90 DAY);")
# 处理结果
echo "$EXPIRED_USERS" | grep -v "user" | while read -r user host; do
if [ -n "$user" ]; then
log "删除过期用户: $user@$host"
mysql_exec "DROP USER '$user'@'$host';"
if [ $? -eq 0 ]; then
log "用户 $user@$host 删除成功"
else
log "用户 $user@$host 删除失败"
fi
fi
done
log "过期用户清理完成"
}
# 执行脚本
main常见问题及解决方案
忘记 root 密码
Linux 系统
bash
# 1. 停止 MySQL 服务
systemctl stop mysqld
# 2. 以跳过授权表方式启动
mysqld --skip-grant-tables --skip-networking &
# 3. 无密码登录
mysql -u root
# 4. 修改 root 密码
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewRootPassword1!';
# 5. 重启 MySQL 服务
pkill mysqld
systemctl start mysqldWindows 系统
- 停止 MySQL 服务(服务管理器或命令行)
- 在命令行中启动 MySQL:cmd
mysqld --skip-grant-tables - 另开命令行,无密码登录:cmd
mysql -u root - 修改密码:sql
FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewRootPassword1!'; - 重启 MySQL 服务
用户无法登录
| 问题 | 解决方案 |
|---|---|
| 密码错误 | 重置密码 |
| 主机限制 | 检查用户的 host 配置 |
| 账户锁定 | 解锁账户 |
| 密码过期 | 修改密码 |
| 认证插件不匹配 | 切换认证插件 |
| 权限不足 | 检查防火墙或网络配置 |
查看登录失败日志
sql
-- 查看登录失败次数
SHOW GLOBAL STATUS LIKE 'Connection_errors_denied';
-- 查看错误日志
SHOW VARIABLES LIKE 'log_error';
-- 然后查看该日志文件总结
MySQL 用户管理是数据库安全的基础,通过合理创建、配置和管理用户,可以提高数据库的安全性和可靠性。
建议:
- 定期审查用户列表和权限
- 遵循最小权限原则
- 使用强密码策略
- 限制用户连接来源
- 监控用户活动
- 定期备份用户权限
通过本文的介绍,您应该掌握了 MySQL 用户的创建、修改、删除和管理的方法,以及相关的最佳实践。
