深色模式
MySQL 用户与权限
摘要:业务账号必须遵循最小权限原则——只给需要的库、只给需要的操作、只给需要的来源 IP。本文给出建账号、授权、回收、角色复用与权限排查的完整命令。
适用环境
bash
# 以管理员身份登录
mysql -uroot -p
# 查看当前有哪些账号(重点关注 host 为 % 的)
SELECT user, host, plugin FROM mysql.user;1
2
3
4
5
2
3
4
5
操作步骤
1. 创建业务账号(强密码 + 限制来源)
sql
CREATE USER 'app_rw'@'10.0.1.%' IDENTIFIED BY 'Str0ngPass!2026';
CREATE USER 'app_ro'@'10.0.1.%' IDENTIFIED BY 'Str0ngPass!2026';1
2
2
2. 按最小权限授权
sql
-- 读写账号:只有一个库的增删改查
GRANT SELECT, INSERT, UPDATE, DELETE ON shopdb.* TO 'app_rw'@'10.0.1.%';
-- 只读账号:报表、查询平台
GRANT SELECT ON shopdb.* TO 'app_ro'@'10.0.1.%';1
2
3
4
5
2
3
4
5
危险
GRANT ALL PRIVILEGES ON *.* TO 'app'@'%' 是典型事故源头:等同于把整实例交给应用,误操作与删库风险极高。生产环境禁止使用,也不要给业务账号 SUPER/FILE/DROP 权限。
3. DBA 管理账号与角色复用
sql
-- 用角色统一管理一类权限,避免逐个账号授权
CREATE ROLE 'role_readonly';
GRANT SELECT ON shopdb.* TO 'role_readonly';
GRANT 'role_readonly' TO 'app_ro'@'10.0.1.%';
SET DEFAULT ROLE ALL TO 'app_ro'@'10.0.1.%';1
2
3
4
5
2
3
4
5
4. 回收权限与删除账号
sql
REVOKE DELETE ON shopdb.* FROM 'app_rw'@'10.0.1.%';
SHOW GRANTS FOR 'app_rw'@'10.0.1.%';
DROP USER 'app_ro'@'10.0.1.%'; -- MySQL 8.0 中 DROP USER 会一并清除权限1
2
3
4
2
3
4
5. 改密码与限制资源(可选)
sql
ALTER USER 'app_rw'@'10.0.1.%' IDENTIFIED BY 'AnotherPass!2026';
ALTER USER 'app_rw'@'10.0.1.%' WITH MAX_CONNECTIONS_PER_HOUR 0
MAX_USER_CONNECTIONS 50; -- 限制该账号最多 50 个连接,防止打满实例1
2
3
2
3
6. 生效与排查
sql
FLUSH PRIVILEGES; -- 仅手工改 mysql.* 表时需要;GRANT/CREATE 不用1
bash
# 连接报错时定位:是账号不存在、密码错还是 host 不匹配
mysql -uapp_rw -p -h 10.0.1.10 -e "SELECT CURRENT_USER(); SHOW GRANTS;"1
2
2
验证
sql
-- 用 app_rw 登录后尝试越权操作,应报 ERROR 1142
SELECT * FROM shopdb.orders LIMIT 1; -- 成功
DROP TABLE shopdb.orders; -- 应被拒绝1
2
3
2
3
bash
mysql -uapp_ro -p -h 10.0.1.10 -e "INSERT INTO shopdb.orders VALUES();" # 应报无权限1
常见坑
WARNING
MySQL 中 'app'@'localhost' 与 'app'@'%' 是两个不同账号,权限互不影响;连不上时先确认实际匹配的是哪一条(用 CURRENT_USER() 查看)。
WARNING
MySQL 8.0 移除了 GRANT ... IDENTIFIED BY 的隐式建用户语法,必须先 CREATE USER 再 GRANT。
WARNING
REVOKE 的库表范围必须与 GRANT 时完全一致才能生效,粒度不同不会报错但权限仍在。
DANGER
删除库表前请确认当前登录账号;使用 root 执行日常操作,等于绕过了所有最小权限保护。