MySQL 中践行最小权限原则,核心是“只授予完成任务所必需的权限,且限定到最细粒度的对象(库、表、列)和操作类型”。不是给一个账号配个
GRANT ALL图省事,而是按角色、按应用、按环境逐一分配。
按角色划分权限边界
不同人员/系统承担不同职责,权限必须隔离:
开发人员:通常只需对测试库的SELECT, INSERT, UPDATE, DELETE权限,禁止访问生产库;可额外授予
SHOW VIEW或
EXECUTE(若用视图或存储过程);不赋予
DROP、
ALTER、
CREATE等 DDL 权限。 运维 DBA:可拥有生产库的
SELECT, RELOAD, PROCESS, SHOW DATABASES等监控类权限;DDL 操作应通过审批流程+专用账号执行,避免长期持有
ALTER ROUTINE或
GRANT OPTION。 应用账号:Web 应用连接数据库的账号,应严格限定为单个业务库,仅开放该应用实际调用的表与操作。例如电商订单服务只需
orders、
order_items表的
SELECT, INSERT, UPDATE,绝不赋予
users表权限。
按对象粒度收缩授权范围
MySQL 支持四级权限层级:全局(
*)、库级(
db.*)、表级(
db.table)、列级(
db.table(col1,col2))。优先使用更细粒度: 避免
GRANT SELECT ON *.* TO 'app'@'%';改用
GRANT SELECT ON myapp.orders TO 'app'@'10.20.30.%'。 敏感字段如
users.phone、
users.id_card可单独收回列级权限:
REVOKE SELECT (phone, id_card) ON myapp.users FROM 'report'@'%',让报表账号只能查脱敏字段。 使用
WITH GRANT OPTION要极度谨慎——它允许被授权者再授予权限,极易造成权限扩散,生产环境应禁用。
按连接来源与生命周期控制账号风险
权限不只是“能做什么”,还包括“从哪来”和“能用多久”:
限制主机范围:'app'@'192.168.10.5'比
'app'@'%'安全得多;内网服务尽量用具体 IP 或子网(如
'app'@'172.16.0.0/255.255.0.0')。 避免使用空密码或弱密码;启用
validate_password插件强制复杂度;定期轮换应用账号密码(尤其在人员变动或安全事件后)。 临时排查账号可设过期时间:
CREATE USER 'tmp_dba'@'%' IDENTIFIED BY 'xxx' PASSWORD EXPIRE INTERVAL 1 DAY;,到期自动锁定。
定期审计与权限收敛
权限不是设完就一劳永逸。需建立常态化清理机制:
用SELECT user, host, account_locked, password_last_changed FROM mysql.user;查看账号状态。 通过
SHOW GRANTS FOR 'user'@'host';检查实际权限,对比当前业务需求,移除冗余项(如已下线模块残留的表权限)。 结合 MySQL 8.0 的角色(
CREATE ROLE)统一管理权限组,例如
role_readonly、
role_order_rw,再将角色赋予用户,便于批量调整与复用。
最小权限不是过度限制,而是让每个账号能力刚好够用、暴露面刚好可控。它需要前期梳理清楚数据流向和功能依赖,也需要后期持续跟踪业务变化。不复杂但容易忽略。
