必须用alter user显式设置max_user_connections,set global max_user_connections对已有用户完全无效;它仅影响新用户默认值,不修改现存账号限制。alter user直接更新mysql.user表中max_user_connections字段,立即生效,无需重启或flush privileges;host必须与show grants输出逐字一致,设为0表示不限制,验证需查表并实测触发error 1226。

必须用 ALTER USER 显式设置 MAX_USER_CONNECTIONS,SET GLOBAL max_user_connections 对已有用户完全无效——它只影响后续新建用户的默认值,不改任何现存账号的限制。
用 ALTER USER 设置已有用户的连接上限
生产环境绝大多数情况是给已存在账号加限,ALTER USER 是唯一推荐方式。它直接更新 mysql.user 表的 max_user_connections 字段,立即生效,无需重启、无需 FLUSH PRIVILEGES。
-
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 10;—— host 必须和SHOW GRANTS FOR 'app_user'@'%'输出完全一致 -
'app_user'@'localhost'和'app_user'@'127.0.0.1'是两个独立账号,得分别执行 - 设为
0表示不限制(退回到全局max_connections约束),不是“禁止登录” - 设为
1就真只允许 1 个活跃连接,第 2 次新建连接会立刻报错:ERROR 1226 (42000): User 'app_user' has exceeded the 'max_user_connections' resource
验证配置是否真正写入系统表
很多人执行完 ALTER USER 就以为完事了,但没查表等于没设。唯一可信路径是直查 mysql.user:
- 执行:
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user'; - 返回的
max_user_connections值必须是你设的正整数,不能是NULL或0 - 注意字段名是全小写
max_user_connections,不是大写或驼峰 - 如果返回
0或空,说明命令没生效,大概率是 host 不匹配(比如用了'%'但用户实际从'192.168.1.100'连入)
检查当前活跃连接数并实测触发限制
SHOW PROCESSLIST 只显示当前连接,而 MAX_USER_CONNECTIONS 只在校验**新建连接**时触发。旧连接不会被踢,所以看到超限数量 ≠ 配置失效。
- 查实时活跃连接(需开启
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 - 错误信息里带
(current value: N)才算真正生效;若报的是ERROR 1040: Too many connections,那是全局max_connections满了,不是用户级限制在起作用
连接池配置必须 ≤ 用户限制值
这是最容易被忽略的落地环节。应用层若用 HikariCP、Druid 等连接池,其 maximumPoolSize(或等效参数)必须 ≤ 对应账号的 MAX_USER_CONNECTIONS 值。
- 否则应用启动或首次压测就会失败,日志反复出现
ERROR 1226,连接池不会自动降级或重试 - 多个微服务共用同一账号(如
'app'@'%'),各自连接池都配了 20,总连接数轻松突破 100 - 空闲连接未释放(比如
wait_timeout太长)也会卡满配额,需同步检查应用close()行为和连接池idle_timeout配置
真正卡住的往往不是“设没设”,而是 host 匹配不严、连接池配超、或者空闲连接挂太久占着坑不走——这三个点漏一个,限制就形同虚设。











