<p>MySQL中限制单个用户最大连接数必须用GRANT USAGE ON . TO 'user'@'host' WITH MAX_USER_CONNECTIONS N,设为0表示不限制,执行后需FLUSH PRIVILEGES生效;该限制仅作用于新建连接,且需匹配精确host(如'%'与'localhost'视为不同用户)。</p>

如何用 GRANT 限制单个 MySQL 用户的连接数
MySQL 允许对每个用户单独设置最大并发连接数,这比全局调高 max_connections 更安全——能防止单个应用或误配脚本把整个数据库拖垮。
语法很简单,但必须用 GRANT 语句(不是 CREATE USER),且需有 CONNECTION_ADMIN 或 SUPER 权限:
GRANT USAGE ON *.* TO 'app_user'@'%' WITH MAX_USER_CONNECTIONS 20;
关键点:
-
USAGE表示只授予权限控制,不赋予任何数据库操作权限,适合纯连接限制场景 - 必须指定主机名(如
'%'或'192.168.1.%'),'app_user'@'localhost'和'app_user'@'%'是两个独立用户 - 设为
0表示不限制(等同于没设),设为正整数才生效 - 执行后需
FLUSH PRIVILEGES;才能立即生效,无需重启 MySQL
为什么不能只靠全局 max_connections 控制资源
全局 max_connections 是总闸门,但挡不住某个用户独占全部额度。比如你设了 max_connections = 500,而一个没做限制的 app_user 可能自己就建了 480 个连接,其他服务全被拒绝。
更糟的是,这类连接堆积往往来自应用层 bug:连接未 close、连接池配置错误、重试逻辑失控。这时候全局调高只会掩盖问题,甚至加速 OOM。
真实排查线索:
- 查
SHOW PROCESSLIST;看大量连接是否来自同一User和Host - 监控
Threads_connected和Threads_running差值,若前者远大于后者,说明大量空闲连接未释放 - 检查
information_schema.processlist中Time字段,长时间Sleep的连接大概率是泄漏源
配合 wait_timeout 防止连接长期闲置
光限制数量不够,还得让空闲连接自动断开。否则即使设了 MAX_USER_CONNECTIONS 20,20 个连接全挂着 Sleep 1 小时,新请求照样进不来。
推荐组合设置:
- 对应用用户单独设会话级超时:
SET SESSION wait_timeout = 60;(单位秒) - 在配置文件中设全局默认:
[mysqld] wait_timeout = 60,影响所有新连接 - 注意
interactive_timeout是给交互式客户端(如 mysql 命令行)用的,一般不用动 - 应用层也要配好连接池的
maxLifetime和idleTimeout,和数据库超时协同,避免“假死”连接
容易被忽略的系统级限制
MySQL 层面的限制只是第一道关。Linux 内核对每个进程能打开的文件描述符(file descriptor)有硬限制,默认常为 1024。一个 MySQL 连接至少占用 1 个 fd,如果 max_connections 设到 2000,但系统限制卡在 1024,MySQL 启动时就会报错或静默降级。
确认和调整方法:
- 查当前限制:
cat /proc/$(pgrep mysqld)/limits | grep "Max open files" - 临时提高(仅本次启动有效):
sudo prctl -r --set-rlimit nofile=65536 $(pgrep mysqld) - 永久生效:修改
/etc/security/limits.conf,加两行:mysql soft nofile 65536mysql hard nofile 65536,再确保 systemd 服务没覆盖它(检查/etc/systemd/system/mysqld.service.d/override.conf是否有LimitNOFILE=)
真正上线前,别只盯着 MySQL 参数——ulimit -n、内存、连接池配置、应用层连接生命周期管理,漏掉任何一环,都可能让连接数在半夜突然飙红。


















