mysql中授予用户只读权限需显式执行grant select on db_name.* to ‘user’@’host’,禁用grant option,避免误用usage;读写权限则授select,insert,update,delete,禁用all privileges及高危权限。

MySQL 中如何授予用户只读权限
只读权限意味着用户只能执行 SELECT,不能修改数据或结构。最稳妥的做法是显式授予 SELECT 权限,且不授予其他 DML 或 DDL 权限。
常见错误是误用 USAGE(它实际表示“无任何权限”,不是只读)或遗漏 GRANT OPTION 的禁用(否则用户可能自行授权他人)。
- 对单个数据库授只读:使用
GRANT SELECT ON `db_name`.* TO 'user'@'host'; - 若需跨库只读,需为每个库单独执行
GRANT SELECT;MySQL 不支持通配多个库名 - 执行后必须运行
FLUSH PRIVILEGES;(仅在直接操作mysql系统表后才强制需要;通过GRANT语句赋权通常自动生效,但部分旧版本或特殊部署建议刷新) - 注意:视图、存储过程等对象的访问还取决于其定义者权限和
SQL SECURITY设置,SELECT权限本身不自动覆盖这些
MySQL 中如何授予用户读写权限
读写权限一般指允许 SELECT、INSERT、UPDATE、DELETE,但不含结构变更(如 CREATE、DROP)。这是应用账号最常见的最小权限模型。
不要直接授予 ALL PRIVILEGES —— 它包含 GRANT OPTION、ALTER ROUTINE、FILE 等高危权限,极易引发越权或安全风险。
- 标准读写(不含建表/删表):
GRANT SELECT, INSERT, UPDATE, DELETE ON `db_name`.* TO 'user'@'host'; - 如果应用需要清空表(
TRUNCATE),注意:MySQL 中TRUNCATE需要DROP权限(因其本质是删表重建),不是DELETE权限能覆盖的 - 若业务涉及临时表(如子查询物化),还需额外授予
CREATE TEMPORARY TABLES权限 - 权限作用域尽量精确到库(
`db_name`.*),避免用*.*;生产环境禁止对mysql系统库授任何非 dba 用户权限
撤销权限与检查当前权限
权限变更后,务必验证是否生效。MySQL 不会自动回收已存在的活跃连接的权限缓存,旧连接仍持有赋权前的权限快照,需重新登录或等待连接复用失效。
- 撤销某类权限:
REVOKE INSERT, UPDATE ON `db_name`.* FROM 'user'@'host';(注意:不是DROP,而是REVOKE) - 查看用户所有权限:
SHOW GRANTS for 'user'@'host'; - 查看当前会话权限:
SHOW PRIVILEGES;不显示当前用户权限,应改用SELECT * FROM INFORMATION_SCHEMA.ROLE_TABLE_GRANTS;(8.0+)或更直接的方式:SELECT CURRENT_USER(), USER();+SHOW GRANTS; - 权限继承关系复杂:角色(8.0+)可简化管理,但若用角色,需确认用户已
SET default ROLE,否则角色权限不会激活
常见权限相关错误与绕过风险
权限配置看似简单,但几个关键点容易被忽略,导致“以为限制了,其实没生效”:
-
localhost和127.0.0.1在 MySQL 中被视为不同 host —— 用户'user'@'localhost'和'user'@'127.0.0.1'是两个独立账户,权限需分别设置 - 通配符主机名(如
'user'@'%')优先级低于具体 IP,但若存在'user'@'192.168.1.%'和'user'@'%',MySQL 按最长匹配原则选择,不是按书写顺序 - 即使用户只有
SELECT权限,若其能访问INFORMATION_SCHEMA(默认所有用户可查),就能枚举库表结构;如需进一步收敛,需用--skip-show-database启动参数或限制SHOW DATABASES权限(8.0.12+ 支持SHOW DATABASES权限开关) - 函数/存储过程执行权限独立于表权限:即使用户无
SELECT权限,只要拥有EXECUTE权限且过程定义为SQL SECURITY DEFINER,就可能间接读取数据 —— 这是典型的权限绕过场景
权限粒度控制在 MySQL 里不是一劳永逸的事,尤其当引入视图、过程、事件或复制拓扑时,权限上下文会动态变化。上线前最好用目标用户账号实际执行一遍典型 SQL 流程,而不是只依赖 SHOW GRANTS 输出判断。