唯一生效方式是ALTER USER设置MAX_USER_CONNECTIONS;SET GLOBAL仅影响未显式设限的新用户;需核对host一致性、查mysql.user表确认值、区分MAX_CONNECTIONS_PER_HOUR用途及连接池配置约束。

用 ALTER USER 设置 MAX_USER_CONNECTIONS 才生效
直接改 SET GLOBAL max_user_connections 对已有用户完全没用,它只影响“未显式设置过限制”的新用户。真正起效的唯一方式是执行 ALTER USER 语句,比如:
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 8;
注意三点:
-
app_user@%中的 host 必须和SHOW GRANTS FOR 'app_user'@'%'输出的完全一致;'app_user'@'localhost'和'app_user'@'127.0.0.1'是两个独立账号,得分别设限 - 设为
0表示不限制(退回到全局max_connections约束),不是禁止登录 - 该操作直接更新
mysql.user表的max_user_connections字段,立即生效,无需FLUSH PRIVILEGES或重启
验证配置是否真写进去了
别信 SHOW PROCESSLIST —— 它只显示当前已连上的连接,而 MAX_USER_CONNECTIONS 只在校验**新建连接**时触发。旧连接不会被踢,所以看到 12 个连接不等于配置失效。
查配置是否落库,执行:
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user';
返回值必须是你设的数字(比如 8),不能是 NULL 或空行。如果为 NULL,说明根本没设置成功;如果查不到记录,可能是用户名或 host 拼错。
再查真实活跃连接数(排除后台线程干扰):
SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND user = 'app_user';
用 MAX_CONNECTIONS_PER_HOUR 控制脚本调用频率
这个参数和并发连接数无关,它只限制“每小时能新建多少次连接”,适用于定时脚本、ETL 工具这类短连接场景。
必须在创建或修改用户时显式指定,例如:
ALTER USER 'etl_user'@'10.20.%' WITH MAX_CONNECTIONS_PER_HOUR 60;
常见误区:
- 它不统计单个连接内的查询次数,只数“新连接建立”动作
- 连接池复用、长连接、
mysql -e一次性命令都算一次新连接 - MySQL 没有全局
MAX_CONNECTIONS_PER_HOUR配置项,只能按账号设 - 报错是
ERROR 1226 (42000),但错误信息里会明确写 “exceeded the 'max_connections_per_hour' resource”
连接池配置必须 ≤ 用户限制值
应用层用了 HikariCP、Druid、SQLAlchemy 等连接池,其 maximumPoolSize(或等效参数)必须 ≤ 对应账号的 MAX_USER_CONNECTIONS 值。否则启动就失败,且连接池不会自动降级。
典型踩坑点:
- 多个微服务共用同一账号(如
'app'@'%'),各自配了maximumPoolSize=20,总连接数轻松突破 100 - 空闲连接没及时释放:
wait_timeout太长 + 连接池idleTimeout没配,导致 8 个限额被 8 个 Sleep 连接占满,新请求全卡住 - 误以为限制的是“总连接数”,其实只管“同时活跃连接数”;一个连接执行完 SQL 后还挂着 Sleep,也算在限额内
真正要防的不是并发峰值,而是连接泄漏和空闲堆积——光设 MAX_USER_CONNECTIONS 不调 wait_timeout 和连接池 idle 参数,等于只装了门锁却忘了关窗。


















