生产环境应严格遵循最小权限原则:只授具体数据库权限,禁用all privileges和.,按需分配select/insert/update/delete等细粒度权限,优先使用角色管理,禁用flush privileges冗余操作,并确保host匹配精准、禁用dns解析。
权限粒度要按需收缩,别直接 GRANT ALL ON *.*
给用户分配 ALL PRIVILEGES 且作用域为 *.* 是最常见也最危险的授权方式。它绕过所有精细化控制,一旦账号泄露或误操作,后果不可控。生产环境应严格遵循最小权限原则:
- 只授予具体数据库(如
myapp_db),而非*.*或myapp_%这类模糊匹配 - 避免使用
GRANT OPTION,除非明确需要该用户转授权限 - 对只读服务(如报表、监控)仅授予
SELECT;对定时任务账户,通常只需INSERT, UPDATE, DELETE,不给DROP或ALTER - 注意
USAGE权限看似“无权”,实为创建账号但不赋任何操作权限的占位符,适合预留账号
用角色(ROLE)管理权限组,别反复 GRANT/REVOKE 单个用户
MySQL 8.0+ 支持角色,这是提升授权效率的关键机制。直接对每个用户重复执行 GRANT 不仅易出错,还让权限状态难以审计。正确做法是:
- 先创建角色,如
CREATE ROLE 'app_writer',再批量授权:GRANT INSERT, UPDATE, DELETE ON myapp_db.* TO 'app_writer' - 把角色赋予用户:
GRANT 'app_writer' TO 'svc_user'@'10.20.30.%' - 启用角色需显式调用:
SET ROLE 'app_writer'(会话级)或设为默认:SET DEFAULT ROLE 'app_writer' TO 'svc_user'@'10.20.30.%' - 权限变更只需改角色,所有绑定该角色的用户自动生效,无需遍历重授
避免频繁刷新权限,别在脚本里反复执行 FLUSH PRIVILEGES
FLUSH PRIVILEGES 并非授权必需步骤——只要用标准 GRANT/REVOKE 语句,MySQL 会自动重载权限缓存。手动执行它反而可能引发问题: