mysql限制脚本每小时新建连接数须用max_connections_per_hour,仅统计成功认证的新连接,需通过grant usage on . to 'user'@'host' with max_connections_per_hour n设置,主机名必须精确匹配,计时窗口为自然小时,超限报错error 1226。

限制脚本每小时新建连接数:用 MAX_CONNECTIONS_PER_HOUR
它只拦「新连」,不拦查询,也不管连接池复用。如果你的 Python 脚本每次执行都 pymysql.connect() 再 close(),这个参数就管用;如果用了 pool = create_engine(..., pool_pre_ping=True),那基本没效果。
- 必须用
GRANT USAGE ON *.* TO 'script_user'@'%' WITH MAX_CONNECTIONS_PER_HOUR 60设置,CREATE USER里写无效 - 主机名要完全匹配:
'script_user'@'192.168.1.%'和'script_user'@'192.168.1.100'是两个账号,得分别设 - 超限报错是
ERROR 1226 (42000): User 'script_user' has exceeded the 'max_connections_per_hour' resource - 计时窗口是自然小时(00:00–00:59、01:00–01:59…),不是滑动窗口,13:59 连了 60 次,14:00 就重置
限制脚本每小时执行语句总数:用 MAX_QUERIES_PER_HOUR
它统计所有非管理语句(SELECT、INSERT、UPDATE、DELETE),但不区分快慢、不分类型——一条 SELECT COUNT(*) FROM huge_table 和一百条 SELECT 1 都算 1 次。不适合控 QPS,适合防长期滥用。
- 必须带权限重授:
GRANT SELECT ON mydb.* TO 'script_user'@'%' WITH MAX_QUERIES_PER_HOUR 3600,仅ALTER USER不生效 - 设为 0 表示不限;设为正整数才启用;MySQL 5.7.21+ / 8.0.3+ 才支持语法
- 某些 ORM 会自动发
SELECT @@version或SELECT DATABASE()探测,这些也计入配额 - 验证是否生效:查
SHOW GRANTS FOR 'script_user'@'%',再跑脚本循环SELECT 1看是否触发ERROR 1226
限制脚本并发连接数:用 MAX_USER_CONNECTIONS
这是真正卡住“同时有多少个连接活着”的开关。对 PHP 脚本、Java 应用、甚至 phpMyAdmin 都直接有效——因为它们默认不复用连接,点一次“执行”就建一个新连接。
- 推荐用
ALTER USER 'script_user'@'%' WITH MAX_USER_CONNECTIONS 5,MySQL 5.7.6+ 支持,无需FLUSH PRIVILEGES - 设为 0 表示不限(等同于全局
max_connections),不是“禁止连接” - 旧版本只能
UPDATE mysql.user SET max_user_connections = 5 WHERE User = 'script_user'+FLUSH PRIVILEGES - 超限报错也是
ERROR 1226,但错误信息里写的是'max_user_connections'而不是'max_connections_per_hour'
为什么脚本可能完全不受限?先查这三件事
配置写了≠生效。最常漏的是账号匹配、连接复用、版本兼容性。
- 脚本用的账号是不是你设限的那个?
SELECT User, Host FROM mysql.user看清楚@后面的主机名 - 脚本有没有复用连接?查
SHOW PROCESSLIST,如果Command列大量是Sleep且Time很长,说明连接被复用,MAX_CONNECTIONS_PER_HOUR就失效 - MySQL 版本够不够?
MAX_CONNECTIONS_PER_HOUR要 5.6.3+,MAX_USER_CONNECTIONS在ALTER USER中要用 5.7.6+,低版本只能改表
真正卡住频率,靠单个 MySQL 参数很难兜底。连接数限制容易被连接池绕过,语句数限制对慢查询无感,小时粒度太粗。生产环境建议组合:应用层加 time.sleep() 或令牌桶,Web 层用 Nginx limit_req 拦 HTTP 请求,数据库前加 ProxySQL 做实时速率控制。











