MAX_QUERIES_PER_HOUR是MySQL 8.0+原生支持的账户级限流机制,通过CREATE USER或ALTER USER设置,统计用户每自然小时(00:00起)所有语句总数,超限报ERROR 1226;设为0表示不限,不支持滑动窗口,且连接池复用下所有语句均累计计数。

直接用 CREATE USER 或 ALTER USER 设置 MAX_QUERIES_PER_HOUR,这是唯一可靠、无需刷新权限、且 MySQL 8.0+ 原生支持的方式。
新建测试账号时就带上限制
最干净,避免后续误操作或权限残留。注意必须显式指定 IDENTIFIED BY(即使空密码也要写 IDENTIFIED BY ''),否则语法报错:
CREATE USER 'test_api'@'%' IDENTIFIED BY 't3st123' WITH MAX_QUERIES_PER_HOUR 60;
-
MAX_QUERIES_PER_HOUR统计的是该账号所有语句总数:包括SELECT、SHOW、EXPLAIN,甚至 ORM 启动时的SELECT DATABASE() - 设为
0表示不限制;设为60就是每小时最多 60 条语句,超了立刻报ERROR 1226 (42000): User 'test_api' has exceeded the 'max_questions' resource - 不是“每分钟 1 次”,而是严格按自然小时滚动(从整点 00:00 开始计数),不能改成滑动窗口
给已有测试账号加限制
不用删用户、不用重连、不中断现有连接,ALTER USER 立即生效:
ALTER USER 'test_report'@'localhost' WITH MAX_QUERIES_PER_HOUR 200;
- 如果账号已存在但没设过限制,执行后会覆盖默认的“不限”状态
- 别手抖写成
MAX_QUERY_PER_HOUR(少 s)或MAX_QUESTIONS_PER_HOUR(旧别名,5.7+ 已弃用)——前者语法错误,后者可能静默忽略 - 改完可立刻验证:
SELECT User, Host, max_questions FROM mysql.user WHERE User = 'test_report';,查到的max_questions字段就是当前值
为什么不用 GRANT ... WITH?
因为 GRANT ... WITH MAX_QUERIES_PER_HOUR 在 MySQL 8.0+ 中已被标记为废弃,且逻辑危险:
- 它实际修改的是
mysql.user表里的max_questions字段,但不会同步更新权限缓存,常需手动FLUSH PRIVILEGES - 若用户已有其他权限,
GRANT USAGE可能意外覆盖或混淆已有授权状态 - 官方文档明确说:资源限制应通过
CREATE/ALTER USER设置,GRANT ... WITH仅保留向后兼容,不应在新系统中使用
真正容易被忽略的是:连接池复用同一个账号时,所有连接发出的语句都会累计到这个 MAX_QUERIES_PER_HOUR 额度里——哪怕只开了 1 个连接,循环执行 100 次 SELECT 1,一小时内照样触发限流。它不管语句快慢、不管扫描多少行,只认“次数”。











