alter user 是唯一可靠方式设置已有用户的 max_user_connections 限制,需与 show grants 中的 host 完全一致;设为 0 表示不限制,设为 n 则第 n+1 连接报 error 1226;grant 和 set global 均无效。

必须用 ALTER USER 显式设置,SET GLOBAL max_user_connections 对已有用户完全无效,改了也不生效。
ALTER USER 是唯一可靠方式(MySQL 5.7.6+)
对已存在的账号加限制,只有 ALTER USER 能真正写入 mysql.user 表的 max_user_connections 字段,立即生效,不需 FLUSH PRIVILEGES,也不重启 MySQL。
-
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 10;中的'app_user'@'%'必须和SHOW GRANTS FOR 'app_user'@'%'输出的Host完全一致 -
'app_user'@'localhost'和'app_user'@'127.0.0.1'是两个独立账号,得分别执行ALTER USER - 设为
0表示不限制(退回到全局max_connections约束),不是“禁止登录” - 设为
1就真只允许 1 个活跃连接,第 2 次新建连接会立刻报错:ERROR 1226 (42000): User 'app_user' has exceeded the 'max_user_connections' resource
为什么 GRANT 和 SET GLOBAL 都不靠谱
GRANT ... WITH MAX_USER_CONNECTIONS 只在创建新用户时有效;对已有用户执行,语句不报错但限制根本不会写入表。而 SET GLOBAL max_user_connections = N 更是典型陷阱——它只影响后续新创建用户的默认值,不会动任何现存账号的字段。
- 执行
SET GLOBAL max_user_connections = 5;后查mysql.user,目标用户的max_user_connections字段仍是NULL或旧值 - 压测时突然爆出
ERROR 1226,往往就是误信了这个“全局设置” - MySQL 8.0+ 的系统表字段名是小写
max_user_connections,不是Max_user_connections或驼峰写法
验证是否真生效?别信命令输出,查表 + 实测
配置写进去了,不代表连接池或客户端会守规矩。唯一可信路径是两步:确认字段值、触发超限错误。
- 查配置:
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user';—— 返回值必须是你设的数字,不能是NULL或0 - 查实时连接(需开启
performance_schema):SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND user = 'app_user'; - 手动压测:开多个终端,并发执行
mysql -u app_user -p -e "SELECT 1;",第N+1次(N是你设的上限)应明确报错ERROR 1226
连接池配置必须 ≤ 用户限制值
这是最容易被忽略的落地环节。HikariCP 的 maximumPoolSize、Druid 的 maxActive 等参数,必须 ≤ 对应账号的 MAX_USER_CONNECTIONS 值,否则应用启动或首次压测就会失败,日志里反复出现 ERROR 1226。
- 连接池默认维持 idle 连接,哪怕业务流量为零,也会立刻占满配额
- 多个微服务共用同一账号(如
'app'@'%')时,总连接数会叠加突破限制——建议按实例拆分账号,例如'app_web1'@'10.0.1.10'和'app_web2'@'10.0.1.11' -
MAX_QUERIES_PER_HOUR在 MySQL 5.7.6+ 默认不校验、8.0+ 彻底失效,真要控每小时查询频次,只能靠 ProxySQL 或应用层 Redis + Lua 实现滑动窗口计数











