max_user_connections 是 mysql 对单个用户账号的并发连接数硬限制,非连接池上限;默认为0(不限制),但生产环境需显式设置;通过 alter user ... with max_user_connections 修改,生效无需重启;查实际值应结合 mysql.user 表与 information_schema.processlist。

MAX_USER_CONNECTIONS 是什么,为什么它不等于“连接池上限”
它只是 MySQL 服务端对单个用户账号的**并发连接数硬限制**,和应用层的连接池(比如 HikariCP 的 maximumPoolSize)完全无关。你调大了连接池,但用户账号没放开限制,新连接一上来就会被拒绝,报错:Too many connections for user 'xxx'。
这个值默认是 0,代表“不限制”,但生产环境几乎从不保留 0——因为一个写崩的脚本或恶意账号可能拖垮整个实例。
- 它作用在认证后的会话层面,不是 TCP 连接数,也不是查询并发数
- 修改后立即生效,无需重启 MySQL
- 只限制该用户通过任意 host(比如
'user'@'%')建立的总连接数,不区分客户端 IP
怎么给已有用户设置 MAX_USER_CONNECTIONS
不能用 CREATE USER 重定义,得用 ALTER USER。注意:必须有 CREATE USER 或 UPDATE 权限,且操作的是全局权限表。
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 50;
常见错误:
- 漏掉
WITH关键字,直接写ALTER USER ... MAX_USER_CONNECTIONS 50→ 语法错误 - 对
'app_user'@'10.0.1.%'设了限制,但应用连的是'app_user'@'10.0.1.100'(解析为不同账号)→ 实际没生效 - 设完没刷新权限,误以为要
FLUSH PRIVILEGES→ 不需要,ALTER USER自动持久化并生效
如何查当前用户的 MAX_USER_CONNECTIONS 实际值
别信文档里说的“查 mysql.user 表”,MySQL 8.0+ 的密码和资源限制字段已移入数据字典,直接查表不准。正确方式是:
SELECT User, Host, max_user_connections FROM mysql.user WHERE User = 'app_user';
但更可靠的是看运行时状态:
SELECT user, host, COUNT(*) AS conn_count FROM information_schema.processlist GROUP BY user, host;
这个能告诉你此刻谁占满了配额。注意:information_schema.processlist 只显示当前活跃连接,不包括 sleep 状态但未超时的连接(受 wait_timeout 控制)。
- 如果
max_user_connections显示为 0,说明没显式设置过,走默认不限制 - 如果某用户
conn_count接近你设的上限,但应用报连接失败,大概率是连接没正常 close,或者连接池配置不合理
和 wait_timeout、max_connections 的关系容易搞混
max_connections 是实例级总连接数上限,wait_timeout 决定空闲连接多久被回收,而 MAX_USER_CONNECTIONS 是用户级并发控制。三者叠加才构成完整连接治理。
- 即使
max_connections = 1000,某个用户设了MAX_USER_CONNECTIONS 10,那他最多占 10 个席位 - 如果
wait_timeout太大(比如 28800 秒),sleep 连接长期不释放,会提前耗尽该用户的配额 - Java 应用里,若 HikariCP 的
connection-timeout小于 MySQL 的wait_timeout,可能出现“获取连接超时”而非“连接数超限”——这时候调MAX_USER_CONNECTIONS没用
真正卡住的时候,先看 information_schema.processlist 里是谁在占着不放,再决定调哪个参数。盲目加 MAX_USER_CONNECTIONS 可能把问题掩盖得更深。











