如何使用MySQL grant命令结合Host通配符设置远程授权访问权限?

2026-04-27 21:341阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1019个文字,预计阅读时间需要5分钟。

如何使用MySQL grant命令结合Host通配符设置远程授权访问权限?

MySQL 的 `GRANT` 语句需要明确声明用户可从哪些主机连接,以及哪些数据库和表有权限操作。默认情况下,`host` 字段不可选,其默认值为 `localhost`。

如果你只写 `GRANT ... TO 'user'`,会报错,如 `ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement` 或 `ERROR 1133 (42000): Can't find any matching row in the user table` —— 这是因为没有指定具体的用户实体。

确保在 `GRANT` 语句中包含以下信息:

常见错误写法:

GRANT ALL ON *.* TO 'admin'; -- ❌ 缺少 @host,语法错误

正确写法必须包含 @ 和 host 值:

  • GRANT ALL ON *.* TO 'admin'@'localhost':仅本机可连
  • GRANT ALL ON *.* TO 'admin'@'%':任意 IP(注意防火墙和 bind-address 限制)
  • GRANT SELECT ON sales.* TO 'reporter'@'192.168.5.100':仅来自该 IP 的只读访问
  • GRANT INSERT ON logs.* TO 'writer'@'192.168.5.%':匹配整个 C 段子网

%_host 中的通配行为与 LIKE 不同,不支持混合使用

MySQL 的 host 字段在权限匹配时用的是「字符串前缀匹配」,不是 SQL 的 LIKE 模式。这意味着:

  • '%' 表示「任意长度字符串」,但只允许出现在开头或结尾,不能中间出现(如 '192.168.%.10' 是非法 host 值)
  • '_'host 中无通配含义,就是字面下划线字符,不会被解释为单字符占位符
  • '%.example.com' 合法,表示所有子域名;'db_.prod' 合法,但只匹配字面含 db_.prod 的主机名,不是通配

所以别指望 '192.168._.10' 能匹配 192.168.5.10——它只会当普通字符串查,找不到对应记录。

授权后必须执行 FLUSH PRIVILEGES,否则新权限不生效

MySQL 把权限缓存在内存里,GRANT 只是修改了 mysql.user 表,不会自动重载到运行时权限系统。跳过这步是远程连不上最常被忽略的原因之一。

执行顺序不能颠倒:

  • GRANT(或 CREATE USER + GRANT
  • FLUSH PRIVILEGES

注意:如果用的是 MySQL 8.0+,且之前用户不存在,推荐分两步操作更稳妥:

CREATE USER 'api'@'%' IDENTIFIED BY 'secret123';<br>GRANT SELECT, INSERT ON app_db.* TO 'api'@'%';<br>FLUSH PRIVILEGES;

直接 GRANT ... IDENTIFIED BY 在 8.0+ 中虽支持,但若用户已存在,密码不会被更新(除非加 ALTER USER),容易误以为授权成功实则密码没变。

MySQL 8.0+ 连不上?大概率是 plugin 认证插件不兼容

执行 SELECT host, user, plugin FROM mysql.user,如果看到 root 或你的用户 plugincaching_sha2_password,而客户端(如 Navicat、旧版 JDBC 驱动、某些 Python MySQL 库)不支持,就会报 ERROR 2059 (HY000)

临时解法(开发/测试环境可用):

  • 改回兼容模式:ALTER USER 'api'@'%' IDENTIFIED WITH mysql_native_password BY 'secret123';
  • 立即生效:FLUSH PRIVILEGES;

生产环境建议升级客户端驱动,而不是降级服务端认证方式——caching_sha2_password 更安全,且多数主流工具 2022 年后版本均已支持。

另外确认 bind-address 没被锁死为 127.0.0.1,以及系统防火墙(如 ufwiptables)放行了 3306 端口——这两点不在 SQL 层,但常和 GRANT 问题一起出现,排查时容易漏掉。

标签:Mysql

本文共计1019个文字,预计阅读时间需要5分钟。

如何使用MySQL grant命令结合Host通配符设置远程授权访问权限?

MySQL 的 `GRANT` 语句需要明确声明用户可从哪些主机连接,以及哪些数据库和表有权限操作。默认情况下,`host` 字段不可选,其默认值为 `localhost`。

如果你只写 `GRANT ... TO 'user'`,会报错,如 `ERROR 1290 (HY000): The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement` 或 `ERROR 1133 (42000): Can't find any matching row in the user table` —— 这是因为没有指定具体的用户实体。

确保在 `GRANT` 语句中包含以下信息:

常见错误写法:

GRANT ALL ON *.* TO 'admin'; -- ❌ 缺少 @host,语法错误

正确写法必须包含 @ 和 host 值:

  • GRANT ALL ON *.* TO 'admin'@'localhost':仅本机可连
  • GRANT ALL ON *.* TO 'admin'@'%':任意 IP(注意防火墙和 bind-address 限制)
  • GRANT SELECT ON sales.* TO 'reporter'@'192.168.5.100':仅来自该 IP 的只读访问
  • GRANT INSERT ON logs.* TO 'writer'@'192.168.5.%':匹配整个 C 段子网

%_host 中的通配行为与 LIKE 不同,不支持混合使用

MySQL 的 host 字段在权限匹配时用的是「字符串前缀匹配」,不是 SQL 的 LIKE 模式。这意味着:

  • '%' 表示「任意长度字符串」,但只允许出现在开头或结尾,不能中间出现(如 '192.168.%.10' 是非法 host 值)
  • '_'host 中无通配含义,就是字面下划线字符,不会被解释为单字符占位符
  • '%.example.com' 合法,表示所有子域名;'db_.prod' 合法,但只匹配字面含 db_.prod 的主机名,不是通配

所以别指望 '192.168._.10' 能匹配 192.168.5.10——它只会当普通字符串查,找不到对应记录。

授权后必须执行 FLUSH PRIVILEGES,否则新权限不生效

MySQL 把权限缓存在内存里,GRANT 只是修改了 mysql.user 表,不会自动重载到运行时权限系统。跳过这步是远程连不上最常被忽略的原因之一。

执行顺序不能颠倒:

  • GRANT(或 CREATE USER + GRANT
  • FLUSH PRIVILEGES

注意:如果用的是 MySQL 8.0+,且之前用户不存在,推荐分两步操作更稳妥:

CREATE USER 'api'@'%' IDENTIFIED BY 'secret123';<br>GRANT SELECT, INSERT ON app_db.* TO 'api'@'%';<br>FLUSH PRIVILEGES;

直接 GRANT ... IDENTIFIED BY 在 8.0+ 中虽支持,但若用户已存在,密码不会被更新(除非加 ALTER USER),容易误以为授权成功实则密码没变。

MySQL 8.0+ 连不上?大概率是 plugin 认证插件不兼容

执行 SELECT host, user, plugin FROM mysql.user,如果看到 root 或你的用户 plugincaching_sha2_password,而客户端(如 Navicat、旧版 JDBC 驱动、某些 Python MySQL 库)不支持,就会报 ERROR 2059 (HY000)

临时解法(开发/测试环境可用):

  • 改回兼容模式:ALTER USER 'api'@'%' IDENTIFIED WITH mysql_native_password BY 'secret123';
  • 立即生效:FLUSH PRIVILEGES;

生产环境建议升级客户端驱动,而不是降级服务端认证方式——caching_sha2_password 更安全,且多数主流工具 2022 年后版本均已支持。

另外确认 bind-address 没被锁死为 127.0.0.1,以及系统防火墙(如 ufwiptables)放行了 3306 端口——这两点不在 SQL 层,但常和 GRANT 问题一起出现,排查时容易漏掉。

标签:Mysql