只给select权限不够,必须配合max_queries_per_hour、max_connections_per_hour等账户级资源限制,才能防止报表工具因误操作拖垮数据库;这些限制按自然小时统计语句或连接总数,设为0表示禁止而非不限,需用create/alter user with语法配置。

直接给报表工具用的账号加 MAX_CONNECTIONS_PER_HOUR 或 MAX_QUERIES_PER_HOUR 限制,比单纯给 SELECT 权限更重要——否则一个写错的 JOIN 或没加 LIMIT 的全表扫描就能把数据库拖垮。
为什么只给 SELECT 不够用?
报表工具(比如 Metabase、Superset、FineReport)常会:自动探测表结构、执行预览查询、缓存刷新时并发拉取多张表。这些行为本身不危险,但一旦配置出错或用户手写 SQL 没加条件,就可能触发大结果集或长耗时查询。
-
GRANT SELECT ON report_db.* TO 'report_user'@'%'只控制“能查什么”,不管“能查多频繁”或“能查多大” - 没做资源限制时,一个
SELECT COUNT(*) FROM big_log_table就可能占满连接数或 CPU - MySQL 默认不限制单个用户的查询频次和并发连接数,
report_user和root在资源调度上是平权的
怎么设置低优先级资源限制?
MySQL 5.7+ 支持对用户级资源配额,关键不是“不让它查”,而是“让它查得慢一点、少一点、别抢资源”。用 CREATE USER 或 ALTER USER 设置以下参数:
-
MAX_QUERIES_PER_HOUR 1000:每小时最多执行 1000 条查询(防自动探测/轮询刷爆) -
MAX_CONNECTIONS_PER_HOUR 20:每小时最多建 20 个新连接(防连接泄漏或并发风暴) -
MAX_USER_CONNECTIONS 5:同时最多保持 5 个活跃连接(强制报表工具复用连接池) -
MAX_UPDATES_PER_HOUR 0:明确禁止任何写操作(哪怕误配了INSERT权限也无效)
完整创建命令示例:
CREATE USER 'reporter'@'%' IDENTIFIED BY 'r3p0rt_2026!'
WITH MAX_QUERIES_PER_HOUR 1000
MAX_CONNECTIONS_PER_HOUR 20
MAX_USER_CONNECTIONS 5
MAX_UPDATES_PER_HOUR 0;
之后再授予权限:
GRANT SELECT ON `analytics`.* TO 'reporter'@'%';
容易被忽略的坑:host 匹配和认证插件
报表工具通常从应用服务器 IP 连接,不是本地 localhost,所以 @'localhost' 会连不上:
- 确认实际连接来源 IP,用
'reporter'@'10.20.30.%'比'reporter'@'%'更安全(避免开放到公网) - MySQL 8.0 默认用
caching_sha2_password插件,老版本报表工具可能不支持——创建时显式指定:CREATE USER 'reporter'@'%' IDENTIFIED WITH mysql_native_password BY 'r3p0rt_2026!'; - 创建后立刻验证:
SELECT User, Host, plugin, max_questions FROM mysql.user WHERE User = 'reporter';
验证低优先级是否生效?
别只测“能不能查”,要测“超限时的行为”:
- 用
mysql -u reporter -p -h your-db-host登录后,连续执行 6 次SELECT SLEEP(1);(如果MAX_USER_CONNECTIONS设为 5,第 6 次会报ERROR 1203 (42000): User reporter already has more than 'max_user_connections' active connections) - 在另一个会话里用
SHOW PROCESSLIST;观察reporter的连接是否被标记为unauthenticated user(说明 host 不匹配)或状态为Sleep但长时间不响应(说明资源限制已起作用) - 检查
performance_schema.events_statements_summary_by_account_by_event_name表,看count_star是否卡在配额上限
真正难的不是加权限,而是让这个账号在高负载时“安静地失败”,而不是无声无息吃掉所有可用连接或 CPU 时间片。











