MySQL自身不支持连接速率限流,需依赖iptables、ProxySQL和threads_running三层协同限流,并配合应用层指数退避重连机制防雪崩。

MySQL自身不支持连接速率限流,必须靠外层拦截
MySQL原生没有每秒新建连接数限制功能。max_connections只是总上限,对DDOS无效——攻击者用短连接反复建连断连,wait_timeout根本没机会触发,连接池就已耗尽。真正要拦的是“单位时间新建连接速率”,不是“最多能连多少”。
- 系统层用
iptables或firewalld限速,例如:iptables -A INPUT -p tcp --dport 3306 -m connlimit --connlimit-above 3 --connlimit-mask 32 -j DROP(同一IP每秒最多3个新连接) - 若已部署
ProxySQL或HAProxy,必须在代理层配置rate_limit或stick-table,MySQL后端只处理“已放行”的连接 -
max_connect_errors只防暴力密码爆破,对无认证的TCP洪峰完全无效
threads_running 高水位限流是唯一可行的SQL级硬控制
MySQL内部唯一能实时感知负载并主动拒绝请求的指标是 threads_running(活跃线程数)。当它超过阈值时,可直接丢弃新查询,避免CPU打满或锁等待雪崩。
- 通过
SHOW STATUS LIKE 'Threads_running'实时获取当前值 - 在中间件(如ProxySQL)或应用网关中监听该值,一旦 ≥ 预设阈值(如64),立即返回错误或排队
- 不能仅依赖
max_connections:它只控连接数,不控并发执行数;一个连接可能发10个慢查询,threads_running才反映真实压力 - 注意:该方式需配合低水位FIFO队列,否则突增流量会直接被丢弃,用户体验断崖式下降
ProxySQL 是目前最实用的SQL粒度限流方案
MySQL原生不支持按语句类型、用户、IP做QPS限制。max_user_connections 只能限制并发连接数,无法区分 SELECT 1 探测和真实业务查询。ProxySQL填补了这一空白。
- 配置示例:对高频
SELECT语句按来源IP限流rate_limit=100(每秒100次) - 规则匹配支持正则:
mysql_query_rules.rule_regex='^SELECT.*FROM orders',精准熔断热点表查询 - 必须开启
mysql_query_rules.active=1并执行LOAD MYSQL QUERY RULES TO RUNTIME生效 - 不要把限流全压给MySQL:ProxySQL限流失败时,MySQL仍可能被拖垮,需与系统层
iptables配合使用
应用层健康检查和退避重连比限流更关键
很多雪崩不是因为没限流,而是应用一断就连、狂连、不幂等。连接被杀后瞬间补上10倍新连接,比攻击本身还致命。
- 所有客户端必须实现连接空闲检测:
SELECT 1或PING,失败后不立即重试 - 重连必须带指数退避:
sleep(1s → 2s → 4s → …),最大不超过30秒 - 长事务或批量导入场景下,
wait_timeout不宜低于300秒,否则频繁中断引发重连风暴 - 监控
Aborted_connects突增 +Host 'x.x.x.x' is blocked错误,说明max_connect_errors被误触发,需调高或清空host_cache
threads_running 高水位熔断这三层缺一不可。最容易被忽略的是应用侧退避逻辑——它不解决“限多少”,但决定“限不住时会不会彻底崩”。


















