Proxy User 必须显式开启 check_proxy_users 才生效,且需匹配认证插件、严格按语法授权、客户端显式声明 proxy-user 参数,ProxySQL 不支持该机制。

Proxy User 必须显式开启 check_proxy_users 才生效
MySQL 默认关闭代理用户功能,check_proxy_users 变量为 OFF 时,哪怕 GRANT PROXY 语句执行成功,代理关系也完全不生效。这不是配置遗漏,而是硬性开关。
必须在 MySQL 实例中启用该变量:
- 临时生效:
SET GLOBAL check_proxy_users = ON; - 永久生效:写入
my.cnf的[mysqld]段,加一行check_proxy_users=ON,然后重启 MySQL - 验证是否开启:
SHOW VARIABLES LIKE 'check_proxy_users';,返回ON才算到位
注意:仅开启 check_proxy_users 不够,若使用 mysql_native_password 插件(MySQL 5.7+ 默认),还需同时开启 mysql_native_password_proxy_users=ON;8.0+ 若用 caching_sha2_password,Proxy User 不支持,必须先切回 mysql_native_password。
GRANT PROXY 语法极易出错,host 必须完全一致
代理授权不是普通权限,语法固定且对引号、host、空格极其敏感。常见错误是漏掉 host 或写错格式,导致报错 ERROR 1410 (42000)。
正确写法只有一种:
GRANT PROXY ON 'real_user'@'%' TO 'proxy_user'@'%';
关键点:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
-
'real_user'@'%'中的 host 必须和CREATE USER 'real_user'@'%'完全一致——不能是'real_user'@'localhost',也不能省略引号或写成real_user -
TO后面的'proxy_user'@'%'同样要严格匹配其创建语句中的 host - 执行后必须
FLUSH PRIVILEGES;,否则mysql.proxies_priv表不会更新 - 验证是否写入:
SELECT * FROM mysql.proxies_priv WHERE User='proxy_user' AND Host='%';
客户端连接必须显式声明 --proxy-user 参数
ProxySQL 不支持透传 Proxy User,所以这个机制只在直连 MySQL 时有效。应用必须主动告诉 MySQL “我要以谁的身份运行”,否则 CURRENT_USER() 始终是 proxy_user,权限不会切换。
不同客户端方式不同:
- 命令行:
mysql -upproxy_user -p --proxy-user=real_user - JDBC URL:
?proxyUser=real_user(需驱动 ≥ 8.0.22) - Python mysql-connector-python:
proxy_user='real_user'参数 - PHP mysqli:不支持,需改用 PDO 并设置
PDO::MYSQL_ATTR_PROXY_USER
验证是否成功:SELECT USER(), CURRENT_USER(); ——前者应为 proxy_user@client_ip,后者应为 real_user@%。只有 CURRENT_USER() 决定实际权限。
Proxy User 不能和 ProxySQL 权限映射混用
这是最容易踩的坑:有人想让应用统一连 ProxySQL 的 app_user,再由 ProxySQL 根据请求头或 SQL 内容决定代入哪个真实用户。这行不通。
原因很直接:
- ProxySQL 不解析
--proxy-user参数,也不转发该上下文 - 它只做连接层透传,把
app_user的认证凭据原样发给后端 MySQL,后端看到的就是app_user,根本不知道你要代入谁 - 想实现“统一入口 + 动态身份”,只能放弃 ProxySQL,改用 MySQL 原生连接池(如 Connector/J 的
loadBalance+proxyUser),或在应用层做路由
真正能落地的组合只有一种:应用直连 MySQL,用 --proxy-user 显式声明身份;ProxySQL 则完全绕开,不参与这一层逻辑。

















