<p>CREATE USER 不能直接设置连接数,因资源限制属权限属性,需用 GRANT USAGE ON . WITH MAX_USER_CONNECTIONS N 显式配置,且按 User+Host 账户维度统计。</p>

能限制,但必须用 GRANT 语句显式设置,CREATE USER 本身不支持直接指定连接数。 否则该用户默认继承全局 max_connections,不受隔离约束。
为什么 CREATE USER 不能直接设连接数
MySQL 的账户资源限制(包括 MAX_USER_CONNECTIONS)属于“权限属性”,不是用户创建时的元数据。即使你写了 CREATE USER 'u'@'%' IDENTIFIED BY 'p' WITH MAX_USER_CONNECTIONS 3,MySQL 会忽略 WITH 子句并静默创建无限制用户——这不是 bug,是语法设计如此。
必须走 GRANT 流程才能生效,原因有二:
-
GRANT ... WITH MAX_USER_CONNECTIONS N会写入mysql.user表的Max_user_connections字段; -
CREATE USER只初始化基础字段(如User、Host、authentication_string),不碰资源限制列。
GRANT USAGE 是修改已有用户的唯一安全方式
对已存在用户调整连接数,不能重复执行带权限的 GRANT(比如 GRANT SELECT ON db.* TO ...),否则可能意外覆盖原有权限。正确做法是用 GRANT USAGE —— 它专为修改资源限制而生,不触碰任何权限位。
示例:
GRANT USAGE ON *.* TO 'dev_user'@'localhost' WITH MAX_USER_CONNECTIONS 5;
执行后记得检查是否写入成功:
SELECT User, Host, Max_user_connections FROM mysql.user WHERE User = 'dev_user';
常见错误:
- 漏掉
ON *.*——GRANT USAGE必须指定作用域,ON *.*是唯一合法值; - 没刷权限 —— 虽然多数 MySQL 版本自动刷新,但遇到不生效时可手动执行
FLUSH PRIVILEGES; - 设为
0—— 这表示“不限制”,不是“禁止连接”,别误以为是禁用账号。
连接数统计按 account(User+Host)聚合,不是按 IP 或客户端
MySQL 的 MAX_USER_CONNECTIONS 统计单位是 account,即 User 和 Host 的组合。例如:
-
'app'@'10.0.1.%':所有匹配该网段的连接都计入同一限额; -
'app'@'%':从任意主机连上来的app用户,全部算一个 account; - 若用了通配符
'app'@'%.example.com',那么web1.example.com和web2.example.com上的连接共享限额。
这意味着:如果你希望不同服务实例互不影响,就得为每个实例分配独立账号,比如 'app_web1'@'10.0.1.10' 和 'app_web2'@'10.0.1.11',再分别设限。靠应用层控制 IP 不够可靠,MySQL 层面只认 account。
验证限制是否真正起作用
光看 mysql.user 表里的值不够,得观察实时连接行为。两个关键检查点:
- 查当前活跃连接数:
SELECT user, COUNT(*) FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND user = 'dev_user' GROUP BY user;
注意:这个查询只统计前台连接(即普通客户端连接),不含后台线程; - 模拟超限场景:用脚本开 6 个并发连接(假设限 5 个),第 6 个应失败并报错
ERROR 1203 (42000): User dev_user already has more than '5' active connections; - 注意连接池干扰:如果应用用了 Druid/HikariCP,池中空闲连接仍占名额,需确认
maxActive/maximumPoolSize≤ 用户连接上限,否则池子初始化就会失败。
最容易被忽略的是:限制只在新建连接时检查,已建立的连接不会被踢出。所以测试时要确保旧连接已断开,或重启应用进程清空连接池。


















