max_execution_time可强制中断超时select查询,但仅会话级生效、不覆盖写操作且可能遗留锁。需配合innodb_lock_wait_timeout使用。

MySQL慢查询没被发现,应用就先垮了
慢查询本身不致命,但当它在高并发下堆积、阻塞连接池、拖垮整个数据库线程时,雪崩就发生了。MySQL原生不提供请求熔断或限流能力——这不是配置开个开关就能解决的事,得靠外围协同控制。
用max_execution_time强制中断长查询(5.7.8+)
这是MySQL内核层最接近“熔断”的机制:对单条SELECT语句设置执行时间上限,超时后自动KILL。但它只作用于SELECT,且需客户端显式启用。
-
max_execution_time是会话级变量,必须在执行前SET,不能全局默认生效 - 不适用于INSERT/UPDATE/DELETE,也不影响存储过程内部语句
- 若查询已持有锁再被中断,可能留下未释放的锁,需配合
innodb_lock_wait_timeout一起调 - 示例:
SET SESSION max_execution_time = 2000;<br>SELECT * FROM orders WHERE status = 'pending' AND created_at < NOW() - INTERVAL 7 DAY;
Proxy层做请求限流比MySQL自身更可靠
MySQL没有连接级QPS限制,也没有按SQL模板限流的能力。真正能拦住雪崩的,是前置代理——比如mysql-proxy、ProxySQL或应用网关。
-
ProxySQL支持基于digest(归一化SQL哈希)的规则限流,可对SELECT ... FROM users WHERE id = ?这类高频慢查单独限速 - 注意
mysql-server返回的错误码是1969(Query execution was interrupted),不是标准超时,应用层要识别并降级 - 限流阈值不能只看QPS,还得结合平均响应时间动态调整;否则在慢查询突增时,固定QPS限流反而会把健康请求也堵死
应用端必须自己实现熔断器,别指望数据库兜底
数据库永远不知道你的业务SLA。一次SELECT COUNT(*) FROM huge_log_table耗时8秒,对DBA是慢查,对你服务的P99可能是灾难。
- 用
Hystrix(Java)、resilience4j或自研熔断器,在DAO层包裹关键查询,失败率超30%或平均延迟超1s就打开熔断 - 熔断后不能直接抛异常,得返回缓存兜底数据或空结果,并记录
slow_query_fallback监控指标 - 最容易被忽略的是:连接池配置和熔断器不联动。比如HikariCP的
connection-timeout设成30秒,而熔断器超时设成1秒,结果熔断器刚生效,连接还在池里等着超时,照样占资源
真正的难点不在加限流或设超时,而在于怎么区分“该慢的查”和“不该慢的查”。一个ORDER BY created_at LIMIT 1走了全表扫描,和一个带索引的分页查询,表现可能一样慢,但根因完全不同——这得靠EXPLAIN和slow_log持续归因,而不是靠某一个开关去挡。










