mysql grant命令如何使用_mysql授权实战方法

2次阅读

mysql GRANT命令严格按全局、数据库、表、列、存储过程层级授权,须显式指定主机名,执行后通常自动生效;常见错误为主机名不匹配、localhost与IP权限分离、密码策略不兼容;8.0+支持角色管理权限;生产环境应遵循最小权限原则,如Web应用用select/INSERT/UPDATE/delete/EXECUTE,备份账号加LOCK TABLES/RELOAD,监控账号仅PROCESS/REPLICATION CLIENT。

mysql grant命令如何使用_mysql授权实战方法

grant 命令的基本语法和权限粒度

MySQL 的 GRANT 不是“一键授权”,它严格区分权限层级:全局(*)、数据库(db_name.*)、表(db_name.table_name)、列((col1,col2))甚至存储过程。用错层级会导致权限不生效或过度开放。

最常用的是数据库级授权,例如给用户 'appuser'@'192.168.1.%'myapp_db 的全部操作权限:

GRANT SELECT, INSERT, UPDATE, DELETE ON myapp_db.* TO 'appuser'@'192.168.1.%';
  • 必须显式指定主机名(不能只写 'appuser'),否则默认为 'appuser'@'localhost',远程连不上
  • 权限列表不支持通配符如 CRUD,必须写全或用 ALL PRIVILEGES(慎用)
  • 执行后需运行 FLUSH PRIVILEGES; 才能立即生效(仅在直接改系统表后才必需;正常 GRANT 会自动刷新)

常见错误:access denied 但账号明明存在

典型现象是创建了用户、执行了 GRANT,应用仍报 Access denied for user 'xxx'@'yyy'。根本原因往往是主机名匹配失败:

  • 客户端连接时用的是 IP,但 GRANT 给的是 'user'@'%.example.com'dns 解析失败或反向解析未配置,MySQL 按 IP 匹配,找不到对应账户
  • 用户从本地连却授权给了 'user'@'127.0.0.1',而 MySQL 把 localhost 视为 socket 连接,走的是 'user'@'localhost' 这条记录(二者权限独立)
  • GRANT 后忘了 IDENTIFIED BY 设置密码,或密码策略不兼容(如 MySQL 8.0 默认用 caching_sha2_password 插件,旧客户端不支持)

MySQL 8.0+ 的角色(ROLE)替代重复授权

频繁给多个用户授相同权限(如所有运维人员都要有 SELECT 权限),硬写 GRANT 易出错且难维护。MySQL 8.0 引入角色机制,可先建角色再批量赋予:

CREATE ROLE 'readonly_role';
GRANT SELECT ON *.* TO 'readonly_role';
GRANT 'readonly_role' TO 'dev1'@'%', 'dev2'@'%';
SET DEFAULT ROLE 'readonly_role' TO 'dev1'@'%';
  • 角色本身不带密码,也不可直接登录,纯粹是权限容器
  • 用户被赋予角色后,需执行 SET ROLE 或设为默认角色才真正启用权限
  • 回收权限只需 DROP ROLEREVOKE ... FROM role_name,比逐个用户操作安全

最小权限原则下的实用授权组合

生产环境绝不该用 GRANT ALL PRIVILEGES。以下是几个真实场景的推荐组合:

  • Web 应用后端php/java):GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE ON app_db.* TO 'webapp'@'10.0.2.%'; —— 禁用 DROPCREATEALTER,防止误删表或注入建库
  • 备份账号(mysqldump):GRANT SELECT, LOCK TABLES, RELOAD ON *.* TO 'backup'@'10.0.1.5'; —— RELOAD 是为了 FLUSH LOGSLOCK TABLES 保证一致性,不需要写权限
  • 监控账号(prometheus exporter):GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'monitor'@'10.0.3.%'; —— 只读状态信息,禁用任何数据访问权限

权限缩放不是靠直觉,得看具体命令需要什么权限。比如 SHOW CREATE VIEW 需要 SHOW VIEW 权限,而不仅是 SELECT;调用函数需要 EXECUTE,哪怕函数内部只做 SELECT

text=ZqhQzanResources