MAX_QUERIES_PER_HOUR 是 MySQL 原生账户级 SQL 执行频次限流机制,统计用户任意连续 60 分钟内所有语句总数,超限报错 ERROR 1226;建户用 CREATE USER WITH,改户用 ALTER USER WITH,设为 0 表示不限;失效主因是连接池复用、系统隐式查询计入、未刷权限或拼写错误。
怎么用 MAX_QUERIES_PER_HOUR 限制用户每小时查询次数
直接结论:max_queries_per_hour 是 mysql 原生支持的账户级限流机制,它统计的是「该用户账号在任意连续 60 分钟内发起的所有语句总数」(包括 select、show、explain,甚至某些隐式元数据查询),超限后立即报错 error 1226 (42000): user 'xxx' has exceeded the 'max_questions' resource。
建用户时设置 vs 已有用户修改
两种方式效果一致,区别只在时机:
- 新建用户:
CREATE USER 'api_user'@'%' IDENTIFIED BY 'pwd' WITH MAX_QUERIES_PER_HOUR 300; - 已有用户:
ALTER USER 'report_user'@'localhost' WITH MAX_QUERIES_PER_HOUR 100; - 取消限制(恢复不限):
ALTER USER 'user'@'host' WITH MAX_QUERIES_PER_HOUR 0;(注意:设为0才是“不限”,不是省略)
为什么你设了却没生效?常见踩坑点
这个参数看似简单,但实际中失效频率很高,原因集中在三点:
- 应用用了连接池(如 HikariCP、Druid)——
MAX_QUERIES_PER_HOUR是按「用户身份」累计,不是按连接或会话。一个连接反复执行 300 次SELECT就会触发限流,和连接数无关; - 系统自动查询也被计入:比如某些 ORM 启动时执行
SELECT DATABASE()或SHOW VARIABLES,这些都会消耗额度; - 未刷新权限:用
UPDATE mysql.user直接改表后,必须执行FLUSH PRIVILEGES;,而CREATE/ALTER USER不需要; - 注意拼写:错误写成
MAX_QUERY_PER_HOUR(少 s)或MAX_QUESTIONS_PER_HOUR(旧别名,5.7+ 已弃用)会导致语法错误或静默忽略。
MAX_QUERIES_PER_HOUR 和其他资源限制的区别
它和同类参数不是互斥,而是各自独立计数:
-
MAX_CONNECTIONS_PER_HOUR:统计mysql_real_connect()调用次数(即「新连上 MySQL」的动作),适合防连接风暴; -
MAX_USER_CONNECTIONS:控制该用户「当前同时存活的连接数」,是并发连接上限; -
MAX_QUERIES_PER_HOUR:唯一针对「SQL 执行频次」的硬限流,对读多写少的 API 场景最实用; - 三者叠加时,只要任一超限,对应操作就失败,不会降级或排队。
真正难调的是时间窗口——它不是滑动窗口,而是按 MySQL 服务端小时周期(从整点开始)滚动重置,这点和业务侧理解的“过去 60 分钟”不一致,监控和告警得按服务端时间对齐。

















