当网站遭遇恶意流量或注入式探测,数据库往往成为最先撑不住的环节。攻击者通过大量并发请求、复杂查询或穷举手段,迫使数据库不断申请内存却无法及时释放,最终造成内存资源耗尽、响应停滞甚至进程被杀。要处理这种故障,必须分步骤完成应急恢复与长期加固。

一、紧急止损与故障恢复
发现数据库内存占用异常飙升时,第一目标是让线上业务先恢复可用。如果数据库还能接受管理命令,应当立刻查看当前活跃连接与耗时会话,把明显来自同一攻击源且长时间挂起的连接强制断开。很多关系型数据库都自带管理视图,例如 MySQL 的 information_schema.PROCESSLIST,可以直观看到哪些会话在执行全表扫描或睡眠不结束。
在确认攻击特征后,可通过临时调小数据库最大连接数、开启内存使用上限保护来防止物理内存被吃满。若系统已经僵死无法执行指令,则需从操作系统层面限制数据库进程资源,或在防火墙直接丢弃来自可疑网段的包,为后续排查争取时间。切记不要贸然重启数据库,应先做内存快照或日志备份,否则攻击路径和证据可能丢失。
1.1 识别耗尽内存的会话
以常见数据库为例,可周期性抓取占用内存高的会话标识。下面给出一个简化对照表,帮助判断哪些情况属于异常消耗:
| 会话状态 | 可能原因 | 处理建议 |
|---|---|---|
| 长时间 Sleep | 应用未释放连接,被攻击者利用堆积 | 设置超时自动断开,回收连接池 |
| Executing 且 CPU 高 | 复杂联表或like全模糊查询 | 终止会话,优化索引 |
| 同一IP大量连接 | 分布式攻击或脚本刷接口 | 网络层封禁,应用限流 |
通过上表可以快速分类,运维人员不必盲目杀进程。实际处理中,建议先把同一IP超过正常阈值的连接全部断开,再观察内存曲线是否回落,这样能减少误伤正常用户。
二、溯源攻击类型与封堵入口
内存被耗尽的背后通常有三种常见攻击模式。其一是暴力遍历接口,用脚本高频调用搜索或列表页,触发数据库重复执行重查询;其二是 SQL 注入,攻击者构造特殊参数让数据库做额外解析与临时表创建;其三是利用未关闭的调试接口批量提交事务。只有找到对应入口,才能避免按下葫芦浮起瓢。
溯源时可结合 Web 服务访问日志与数据库审计日志,重点看报错突增时间点前的请求参数。若发现某接口接收了超长字符串或嵌套语句,基本可判定存在注入隐患。网络层可使用云厂商或本地防火墙对异常IP做小时级封禁,应用层则应统一增加参数校验与预编译语句,从根源切断恶意输入。
2.1 应用代码层的必要改造
很多内存耗尽事件源于开发阶段拼接 SQL 字符串。正确做法是所有数据库操作使用预编译与参数绑定,这样数据库只需编译一次执行计划,不会因参数变化反复申请内存。同时,列表查询必须加上分页与最大返回行限制,防止攻击者通过翻页参数拉取海量数据。
另外,连接池配置也常被忽略。若连接池上限大于数据库允许连接数,峰值时会瞬间压垮内存。应将连接池最大活跃数设置为数据库侧的百分之七十左右,并启用空闲回收,让资源始终处于可控范围。
三、长期防护与容量规划
应急解决只是起点,建立常态化防护才能根除隐患。首先应为数据库单独划分内存并配置监控告警,当内存使用率连续五分钟超过百分之八十五就通知值班人员。其次引入 Redis 等缓存层,把热点数据查询挡在数据库之前,即使被刷接口也不会直接冲击后端。
定期做慢查询日志分析也非常重要。不少攻击正是利用了原本就慢的历史接口,因此每周梳理一遍执行时间最长的 SQL,补索引或重写逻辑,既提升正常体验,也缩小被攻击面。最后,建议对核心业务做只读备库,遇到主库异常可快速切换,保证内存故障不直接演变为网站完全不可用。
总结来看,数据库内存资源被耗尽并非不可控灾难。抓住先恢复、再查源、后加固的主线,配合监控与缓存体系,即便再次面临攻击也能把影响降到最低。