max_user_connections是限制单个用户并发连接数的最精准手段;设为0表示不限制(依赖全局max_connections),alter user修改立即生效且无需重启或flush privileges,必须针对每个host单独设置,并确保连接池配置≤该值。

直接用 MAX_USER_CONNECTIONS 限制单个用户并发连接数,是最准、最省事的防资源过载手段;设为 0 就等于没设,别指望调高 max_connections 全局值来解决单用户滥用问题。
ALTER USER 修改已有用户的连接上限
生产环境里绝大多数情况是给已存在的账号加限制,ALTER USER 是唯一推荐方式。它只改连接数,不碰权限、密码或 SSL 设置,且立即生效,无需 FLUSH PRIVILEGES(MySQL 8.0+ 自动刷新)。
-
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 8;—— 执行后马上起效 - 如果用户有多个
host(比如'app_user'@'192.168.1.%'和'app_user'@'localhost'),必须分别执行ALTER USER,它们在mysql.user表里是两条独立记录 - 设为 0 表示不限制(退回到全局
max_connections约束),线上账号不建议留 0,容易被忽略
CREATE USER 或 GRANT 创建新用户时绑定限制
新账号务必在创建阶段就定死连接上限,避免后期疏漏。MySQL 版本差异直接影响写法:
- MySQL 8.0+ 推荐:
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;——USAGE不授任何权限,只设资源限制 - 别写
CREATE USER ... WITH MAX_USER_CONNECTIONS 20在 8.0.16 前会报错,语法不支持
验证限制是否真生效,不是查 SHOW GRANTS
SHOW GRANTS 根本不显示 MAX_USER_CONNECTIONS,它存在 mysql.user 表里,且只在新建连接时校验。已建立的连接不会被踢,所以看 SHOW PROCESSLIST 容易误判。
- 查配置是否写入:
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 次应报错ERROR 1226 (42000): User 'app_user' has exceeded the 'max_user_connections'
连接池配置必须 ≤ 用户连接上限
限制生效后,旧连接不会自动清理,必须靠应用主动断开或等 wait_timeout 触发。空闲连接挂着不动,真实请求反而连不上——这不是配置没生效,而是资源没腾出来。
- HikariCP 的
maximumPoolSize、Druid 的maxActive必须 ≤ 对应账号的MAX_USER_CONNECTIONS - PHP 的 PDO 默认不复用连接,短脚本反复
new PDO()但没unset,可能几秒内就占满配额 - Java 应用启动失败报错
ERROR 1226,大概率是连接池配置越界











