数据库超时是防止单点恶意请求瘫痪服务的最后一道硬闸,而非可选优化手段;MySQL的MAX_EXECUTION_TIME仅对SELECT有效且需版本≥5.7.8,PostgreSQL的statement_timeout虽覆盖全语句但存在客户端断连后仍执行的盲区,真正可靠的是驱动层(如JDBC setQueryTimeout、psycopg2 timeout)与应用层双控,并需按业务容忍度(如P95延迟)精准设定阈值。

数据库超时不是可选配置,而是止损边界
时间盲注不返回错误、不泄露数据,只靠SLEEP()或BENCHMARK()拖住连接。如果查询没被强制中断,一个恶意请求就能让数据库线程卡死几秒甚至几十秒——这不单是慢,是在消耗连接池、阻塞正常请求、放大攻击效果。超时不是“优化手段”,是防止单点恶意请求瘫痪服务的最后一道硬闸。
MySQL 的 MAX_EXECUTION_TIME 只对 SELECT 有效
这个参数常被误认为万能开关,但它有明确限制:
-
MAX_EXECUTION_TIME仅作用于SELECT语句,对INSERT、UPDATE、DELETE完全无效 - 即使对
SELECT,也要求 MySQL ≥ 5.7.8 且未在optimizer_switch中显式关闭该选项(部分云厂商默认关) - 语句级写法必须用注释:
SELECT /*+ MAX_EXECUTION_TIME(2000) */ * FROM users;会话级需SET SESSION max_execution_time = 2000 - 若应用层拼接了
SLEEP(10)进去,它仍是合法SELECT,照样触发——所以仅设服务端超时,不解决根本问题
JDBC 和 psycopg2 的 setQueryTimeout() / timeout= 才真正兜底
驱动层超时能覆盖完整生命周期,包括网络往返、驱动解析、服务端执行、结果返回。但要注意:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
PreparedStatement.setQueryTimeout(3)单位是秒,不是毫秒;psycopg2的cursor.execute(sql, timeout=3)同理 - 值不能按平均耗时拍脑袋定:前端接口 P95 是 400ms,建议设 2 秒;后台导出任务可设 300 秒,但必须异步化,否则 HTTP worker 直接被占满
- 攻击者发 10 个并发
SLEEP(5),服务端若只设 6 秒超时,连接池照样被吃光——所以maxWait和maxActive也得同步收紧
PostgreSQL 的 statement_timeout 看似全面,但有盲区
它对所有语句生效,单位毫秒,比 MySQL 更宽泛。但关键问题是:
- 若客户端已断开(比如 Nginx 超时断连),PostgreSQL 仍会继续执行到
statement_timeout结束,白白浪费资源 - 它无法阻止攻击者用多个短延时请求试探(如
pg_sleep(0.1)× 50 次),因为单次不超限 - 真正起效的,是驱动层 + 应用层双控:比如 Django 的
CONN_MAX_AGE配合options='-c statement_timeout=2000',再加 ORM 层的 query timeout 封装
最易被忽略的一点:超时值必须和业务容忍度对齐,而不是技术指标。设成 1 秒,可能误杀正常慢查;设成 10 秒,等于给攻击者留足探测窗口。它不是越小越好,而是要在“不让用户刷新页面”和“不让攻击者完成一轮探测”之间找那个窄缝。










