MySQL用户权限中host字段应填应用服务器真实出口IP,如'192.168.1.100';填'localhost'仅适用于本地socket连接,填'%'存在安全风险,域名因DNS解析问题不推荐,生产环境须关闭skip_name_resolve并用IP精确匹配。

MySQL 用户权限里 host 字段到底填什么
填 '192.168.1.100' 是最直接的限制方式,但很多人误填 'localhost' 或 '%' 导致白忙活。MySQL 的权限判断严格区分 host:本地连接用 localhost(走 socket),而应用服务器远程连进来默认是 IP 地址或主机名,'localhost' 权限对它完全无效。
常见错误现象:Access denied for user 'appuser'@'192.168.1.100' —— 这说明你建了用户但 host 不匹配;或者连得上却能从任意 IP 连,大概率是用了 '%'。
- 生产环境禁止用
'%',哪怕加了密码也不行 - 如果应用部署在容器或云主机,查清楚它对外暴露的真实出口 IP,不是容器内网 IP,也不是 NAT 后的负载均衡 IP
- 多个应用需分别授权:
CREATE USER 'app_a'@'10.0.2.5' IDENTIFIED BY 'pwd1';、CREATE USER 'app_b'@'10.0.2.6' IDENTIFIED BY 'pwd2';
GRANT 语句必须显式指定 host,不能省略
执行 GRANT SELECT ON mydb.* TO 'appuser' IDENTIFIED BY 'xxx'; 看似简洁,实则危险:MySQL 会默认把 host 设为 '%'(5.7+ 版本已禁用无 host 的语法,但老版本仍存在)。正确写法必须带 @ 符号和具体 host。
使用场景:给 Java 应用配权限时,常因复制粘贴漏掉 @'10.10.20.30',结果权限落到 'appuser'@'%' 上,等于没限制。
- 授权前先确认用户是否存在:
SELECT User, Host FROM mysql.user WHERE User = 'appuser'; - 授完权必须执行
FLUSH PRIVILEGES;,否则改动不生效(尤其手动改表后) - 最小权限原则:只给
SELECT, INSERT,别一上来就ALL PRIVILEGES
应用连接失败时,先查 MySQL 的实际连接来源 IP
你以为应用连的是 10.0.5.10,但 MySQL 日志里看到的是 10.0.5.11?这是典型网络中间件(如 HAProxy、RDS 代理、K8s Service)做了源地址转换。MySQL 只能看到直连它的客户端 IP,不是原始发起方。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
错误排查路径:在 MySQL 里运行 SHOW PROCESSLIST;,看 Host 列显示的实际 IP;再比对你的 GRANT 语句中写的 host 是否一致。
- 云数据库(如阿里云 RDS、腾讯云 CDB)通常不暴露真实客户端 IP,需通过代理协议(PROXY protocol)或白名单控制,此时 IP 绑定要配在控制台,而非 SQL 授权
- 如果用 SSH 隧道或 port forward,MySQL 看到的是隧道终点的 IP,不是开发机 IP
-
max_connections或wait_timeout触发的拒绝连接,错误信息不含 host,容易误判为权限问题
host 填域名有风险,DNS 解析失败会导致授权失效
写 'appserver.example.com' 看起来优雅,但 MySQL 每次验证权限时都会做反向 DNS 查询(取决于 skip_name_resolve 配置)。一旦 DNS 不稳或超时,连接可能卡住或被拒绝,且排查困难。
性能影响:开启 DNS 解析后,每个新连接都多一次 UDP 查询,QPS 高时延迟明显上升;兼容性上,部分 MySQL 分支(如 Percona Server)默认关闭该行为。
- 线上环境强烈建议关闭 DNS 解析:
skip_name_resolve = ON(写进my.cnf并重启) - 关掉之后,host 只支持 IP 或
'%'、'192.168.1.%'这类模式,不能再用域名 - 如果非要用域名,确保所有 MySQL 节点的
/etc/hosts里静态映射准确,且 DNS 服务 100% 可靠
IP 绑定看着简单,真正落地时最容易栽在“以为连的是 A,其实连的是 B”——网络拓扑、代理层、DNS、配置加载顺序,任何一个环节没对齐,权限就形同虚设。










