直接用alter user设置max_user_connections是生产环境限制已有用户并发连接的唯一推荐方式;它仅修改连接上限、不触权限密码、立即生效,且需为每个host单独设置,设为0表示不限制但线上严禁留0。

直接用 ALTER USER 设置已有用户的 MAX_USER_CONNECTIONS
生产环境里绝大多数情况是给已存在的账号加限制,ALTER USER 是唯一推荐方式。它只改连接数,不碰权限、密码或 SSL 设置,且新连接立即受控。
-
ALTER USER 'api_user'@'%' WITH MAX_USER_CONNECTIONS 15;—— 这条语句执行后无需FLUSH PRIVILEGES,MySQL 8.0+ 自动刷新 - 如果用户有多个 host(比如
'api_user'@'192.168.1.%'和'api_user'@'localhost'),必须分别执行ALTER USER,它们是独立账户,不会自动继承 - 设为
0表示不限制(退回到全局max_connections),线上严禁留0,否则等于没限 - 旧连接不受影响,限制只作用于后续新建连接——这点常被误认为“没生效”
创建用户时就绑定 MAX_USER_CONNECTIONS 避免遗漏
新账号务必在创建阶段就定死连接上限,避免上线后补救。MySQL 8.0.16+ 支持 CREATE USER ... WITH MAX_USER_CONNECTIONS,但要注意语法细节。
- 正确写法:
CREATE USER 'batch_job'@'10.0.3.%' IDENTIFIED BY 'pwd' WITH MAX_USER_CONNECTIONS 3;——WITH关键字不能省,也不能写成IDENTIFIED BY ... MAX_USER_CONNECTIONS 3 - 兼容老版本(如 MySQL 5.7):先
CREATE USER,再用GRANT USAGE ON *.* TO 'user'@'host' WITH MAX_USER_CONNECTIONS N; - 连接池容易掩盖问题:一个 Java 应用配了 10 个连接的 HikariCP,实际可能瞬间占满你设的 8 连接限额,得按应用行为预估而非单纯看单次调用
验证配置是否真起作用,别只查 mysql.user 表
查 mysql.user 表只能确认配置值写进去了,不代表运行时拦截有效。必须结合实时连接数和错误反馈验证。
- 查配置:
SELECT User, Host, Max_user_connections FROM mysql.user WHERE User = 'batch_job';—— 确保返回的是你设的数字,不是NULL或0 - 查实时连接:
SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND user = 'batch_job' GROUP BY user;—— 要求performance_schema已启用 - 手动触发错误:
for i in {1..10}; do mysql -u batch_job -p'pwd' -h db-host -e "SELECT 1;" & done; wait,第N+1次应报ERROR 1226 (42000): User 'batch_job' has exceeded the 'max_user_connections' resource limit
MAX_USER_CONNECTIONS 不是内存限制,宕机还得靠 cgroup
很多人以为设了 MAX_USER_CONNECTIONS 就高枕无忧,其实它只堵连接数,不控内存。每个连接仍会分配 sort_buffer_size、join_buffer_size 等会话级缓冲区,大量连接叠加照样吃光内存。
-
innodb_buffer_pool_size是全局共享的,无法按用户隔离;sort_buffer_size可被客户端SET覆盖(除非你禁掉SET权限) - 真正防宕机必须双管齐下:账号侧用
MAX_USER_CONNECTIONS控连接数,系统侧用cgroup v2(如systemd MemoryMax)锁死整个mysqld进程的内存上限 - 仅调小 MySQL 配置参数不可靠:InnoDB 动态申请内存,OS page cache 和 swap 会让实际占用远超配置值
最容易被忽略的一点:连接限制生效的前提是用户账号的 host 完全匹配。写成 'user'@'192.168.%' 却从 192.168.2.5 连进来,匹配不到,限制就形同虚设。











