alter user是mysql 5.7.6+限制单用户最大连接数的唯一推荐方式,无需重启、立即生效,仅校验新建连接,设为0表示不限制;主机名必须精确匹配,需查mysql.user表验证且连接池配置不得超过该值。

直接用 ALTER USER 设置 MAX_USER_CONNECTIONS,5.7.6+ 版本无需重启、立即生效,且只作用于该用户新建连接——这是唯一推荐的生产级做法。
ALTER USER 是修改已有用户的唯一可靠方式
MySQL 5.7.6 起,ALTER USER 支持在线修改用户资源限制,不依赖全局变量,也不影响已有权限或密码:
-
ALTER USER 'app_user'@'192.168.1.%' WITH MAX_USER_CONNECTIONS 10;—— 主机名必须和SHOW GRANTS输出完全一致,'app_user'@'%'和'app_user'@'localhost'是两个独立账号 - 执行后立刻生效,已存在的连接不受影响,但第 11 个新连接会报错
ERROR 1226 (42000) - 设为
0表示不限制(退回到全局max_connections约束),不是“禁止连接” - 必须有
CREATE USER或ALTER USER权限;普通用户无法自行设置
CREATE USER 时就绑定限制,避免后期补漏
新服务上线或初始化账号阶段,一步到位最安全:
- MySQL 8.0+:直接在
CREATE USER语句中指定:CREATE USER 'api_user'@'%' IDENTIFIED BY 'pwd' WITH MAX_USER_CONNECTIONS 5; - MySQL 5.7(不含 .6)或更早:用
GRANT USAGE替代:GRANT USAGE ON *.* TO 'api_user'@'%' WITH MAX_USER_CONNECTIONS 5; - 注意:
CREATE USER ... MAX_USER_CONNECTIONS 5(无WITH)在 8.0.16 前会语法错误 - 如果只是调连接数、不改权限,
GRANT USAGE比GRANT ALL更干净
为什么 SHOW PROCESSLIST 看到的连接数远超设定值?
这不是配置失效,而是你没理解 MAX_USER_CONNECTIONS 的校验逻辑:
- 它只在「新建连接」时检查,已建立的连接(哪怕状态是
Sleep)不会被踢出或拒绝 -
SHOW PROCESSLIST显示的是当前所有连接快照,包括空闲连接;而限制统计的是同一用户身份下「非 Sleep 的活跃连接」 - 真正反映实时占用的是:
SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND user = 'app_user' GROUP BY user; - 连接池(如 HikariCP)维持的 idle 连接仍计入限额,所以
maximumPoolSize必须 ≤MAX_USER_CONNECTIONS,否则启动就报错
验证是否真生效,别只信命令没报错
改完不验证,等于没做。两个动作缺一不可:
- 查系统表确认写入:
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user';—— 返回值必须是你设的数字,不能是NULL或0(除非你真想不限) - 手动压测验证拦截:
for i in {1..15}; do mysql -uapp_user -p -e "SELECT 1" & done,观察从第N+1个起是否稳定报错User 'app_user' has exceeded the 'max_user_connections' resource limit - 注意:MySQL 错误日志里也会记录
ER_USER_LIMIT_REACHED,比客户端提示更准
最容易被忽略的是:限制生效后,旧连接不会自动释放。应用不主动 close()、连接池 idle 时间太长、wait_timeout 设得过大,都会导致“名额被占着但没干活”,新请求连不进来——这不是配置问题,是资源没腾出来。











