alter user 是修改用户连接限制的唯一可靠方式,必须用 alter user 'user'@'host' with max_user_connections n 显式设置;create user 或 grant 需在创建时绑定限制,且应用连接池上限须≤该值。

ALTER USER 是修改已有用户连接限制的唯一可靠方式
直接执行 SET GLOBAL max_user_connections = 10 对已有用户完全无效——它只影响后续新创建用户的默认值。真正起作用的是每个账号在 mysql.user 表中独立存储的 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'是两个不同账号,需分别设置 - 执行后无需
FLUSH PRIVILEGES(MySQL 8.0+ 自动刷新) - 已有连接不受影响,新连接才会被校验和拦截
CREATE USER 或 GRANT 创建新用户时必须绑定限制
新账号务必在创建阶段就定死连接上限,避免后期疏漏。不同 MySQL 版本写法差异明显:
MySQL 8.0.16+ 推荐写法:
CREATE USER 'api_user'@'%' IDENTIFIED BY 'xxx' WITH MAX_USER_CONNECTIONS 20;
MySQL 5.7 及更早版本必须用:
GRANT USAGE ON *.* TO 'api_user'@'%' WITH MAX_USER_CONNECTIONS 20;
关键细节:
-
GRANT USAGE不授任何权限,只设资源限制,安全且精准 - 不能省略
ON *.*,否则语法报错 -
CREATE USER ... WITH MAX_USER_CONNECTIONS在 8.0.16 前不支持,硬写会失败
验证配置是否生效不能只看 SHOW PROCESSLIST
SHOW PROCESSLIST 显示的是当前已建立的连接,而 MAX_USER_CONNECTIONS 只在校验**新建连接**时触发。旧连接不会被踢,所以看到 12 个连接、但限制是 8,不代表配置失效。
真正该查的两个地方:
- 配置是否写入:
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user';—— 返回值必须是你设的数字,不是0或NULL - 真实活跃连接数:
SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND user = 'app_user' GROUP BY user;—— 这个COUNT才是当前占用数 - 手动压测:
mysql -u app_user -p -e "SELECT 1;"连续执行,第N+1次(N是你设的上限)应报错ERROR 1226 (42000): User 'app_user' has exceeded the 'max_user_connections' resource
应用层连接池配置必须 ≤ 用户级限制值
如果应用用了 HikariCP、Druid 或 Laravel 的数据库连接池,其 maximumPoolSize(或等效参数)必须 ≤ 对应账号的 MAX_USER_CONNECTIONS 值。否则启动或压测时必然触发 ERROR 1226,且连接池不会自动降级或重试。
特别容易忽略的点:
- 多个微服务共用同一账号(如
'app'@'%'),但各自连接池都配了 20,总连接数轻松突破 100 - PHP 使用
PDO::ATTR_PERSISTENT => true时,连接长期复用,MAX_USER_CONNECTIONS很快被占满 - 账号按
User + Host组合计数,'app'@'10.0.1.%'下所有 IP 的连接共享同一限额
账户粒度隔离才是根本解法,角色(ROLE)无法继承 MAX_USER_CONNECTIONS,没法批量管理。











