必须分两层设——全局max_connections控制总容量,用户级MAX_USER_CONNECTIONS控制单账号用量;只调其中一个,等于没防住资源耗尽。

直接说结论:必须分两层设——全局max_connections控制总容量,用户级MAX_USER_CONNECTIONS控制单账号用量;只调其中一个,等于没防住资源耗尽。
查当前连接数和上限值
别猜,先确认现状。两个命令必须一起跑:
-
SHOW VARIABLES LIKE 'max_connections';—— 看服务器总上限 -
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'your_user';—— 看具体账号有没有被设限(注意字段名全小写)
常见误判:看到max_user_connections是NULL或0,就以为没限制。其实0表示“不限”,等同于退回到全局max_connections约束,线上账号不建议留0。
改已有用户的并发连接上限
SET GLOBAL max_user_connections = 5对已存在账号完全无效——它只影响后续新创建用户的默认值,不会动mysql.user表里任何现存记录。
- 正确写法:
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 8; - 主机名必须精确匹配:
'app_user'@'127.0.0.1'和'app_user'@'localhost'是两个账号,得分别执行ALTER USER - 改完立即生效,MySQL 5.7.6+ 不需要
FLUSH PRIVILEGES
验证是否真写进去了?只看命令输出没用,必须再查一次mysql.user表,确认max_user_connections字段值是你设的数字,不是NULL或0。
配连接池时必须 ≤ 用户限制值
这是最容易被跳过的落地环节。HikariCP 的maximumPoolSize、Druid 的maxActive、SQLAlchemy 的pool_size + max_overflow,加起来必须 ≤ 对应账号的MAX_USER_CONNECTIONS值。
- 否则应用启动或压测时,会反复报
ERROR 1226 (42000): User 'xxx' has exceeded the 'max_user_connections' resource - 多个微服务共用同一账号(如
'app'@'%'),总连接数会叠加突破限制——建议按实例拆分账号,例如'app_web1'@'10.0.1.10'和'app_web2'@'10.0.1.11'
连接池配置比数据库限制高,等于主动触发错误;但反过来,数据库限制设得太高而连接池太小,又浪费资源。两者得对齐。
为什么SHOW PROCESSLIST看到的连接数还是超了
设了MAX_USER_CONNECTIONS 3,但SHOW PROCESSLIST里看到这个用户有 6 条记录?这不是配置失效,而是校验时机问题。
- MySQL 只在新建连接握手阶段检查限制,已建立的连接不受影响
- 真实原因通常是应用没调
close()、连接池 idle 配置不合理、wait_timeout设得太长(默认 8 小时) - 查实时活跃连接数,该用:
SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND user = 'app_user';
验证是否真生效,唯一可靠方式是开多个终端,用该账号反复执行mysql -u app_user -p -e "SELECT 1;",超过设定值后第 N+1 次必须明确报错ERROR 1226。空闲连接不会自动清理,得靠应用或wait_timeout触发断开。


















