数据库安全连接数限制不是简单的“设个数字”,而是数据库在遭遇连接风暴、密码爆破或应用层连接泄漏时最直接的一道防线。很多生产事故的起点并不是SQL注入,而是连接数被恶意或异常占满,导致正常业务完全无法建立会话。限制连接数并配合分层策略,可以在攻击者尚未执行有效查询前就阻断其资源消耗路径。
连接数限制到底在防什么
数据库的连接资源是有限的,每建立一个会话,数据库都要分配内存、创建线程或进程、维护认证状态和会话变量。攻击者如果持续发起TCP连接,即使不完成认证,也可能让数据库在握手阶段耗尽文件描述符或线程资源。更常见的是应用端连接池配置错误,在流量高峰时瞬间创建数百个空闲连接,把数据库的最大连接数占满。连接数限制的核心目标是保证“合法请求始终有可用连接”,而不是等资源耗尽后再被动重启。
从攻击视角看,连接数限制能显著提高暴力破解成本。默认情况下,MySQL或PostgreSQL允许同一IP建立多个并发连接,攻击者可以并行尝试大量用户名和密码组合。如果限制单IP最大连接数为3到5个,爆破速度会大幅下降。对于分布式僵尸网络发起的慢速连接攻击,全局连接上限和单用户连接上限的组合策略能防止单点资源耗尽。
不同数据库的连接数参数体系
MySQL中,max_connections控制全局最大连接数,但真正容易被忽略的是max_user_connections和max_connect_errors。max_user_connections限制单个账号的并发连接数,适合为不同业务账号设置独立上限。max_connect_errors则用于应对连接握手失败,如果某个IP连续多次认证失败,MySQL会直接拒绝该IP后续连接,直到执行FLUSH HOSTS。这个机制在默认配置下可能过于敏感,但也是一种基础的防爆破手段。
PostgreSQL的连接模型与MySQL不同,每个连接对应一个独立进程,资源开销更大。参数max_connections默认通常为100,生产环境需要结合内核参数和内存容量调整。PostgreSQL没有内置的单IP连接限制,需要借助pg_hba.conf配合外部工具如fail2ban,或者使用连接池中间件实现。对于高并发场景,更推荐使用PgBouncer做连接复用,将数据库的实际连接数控制在合理范围,而不是单纯调大max_connections。
SQL Server的连接限制通过sp_configure的user connections选项配置,默认0表示不限制。但SQL Server更依赖资源调控器(Resource Governor)来限制不同应用组的CPU和内存,连接数限制通常由应用层或防火墙完成。Oracle则通过PROFILE中的SESSIONS_PER_USER参数限制单用户会话数,同时监听器可以设置连接速率限制。
分层限制策略比单一参数更有效
只在数据库层面设置一个全局最大连接数远远不够。一个有效的防护策略至少包含四层:网络层、操作系统层、数据库层和应用层。网络层通过防火墙或安全组限制访问来源IP,只允许应用服务器网段访问数据库端口,从根源上减少攻击面。操作系统层可以使用iptables的connlimit模块或nftables限制单IP并发连接,例如限制每个IP最多同时建立10个到3306端口的TCP连接。
数据库层则根据业务账号和来源IP做细粒度控制。MySQL可以为不同业务账号设置max_user_connections,例如核心交易账号限制50个连接,报表查询账号限制10个连接,防止单个慢查询账号占满全部资源。同时开启performance_schema中的连接统计表,监控哪些账号和IP长期占用连接却不释放。应用层连接池必须设置最大连接数、空闲连接回收时间和连接获取超时,避免应用在数据库重启后无限重试创建连接。
连接数限制与连接池的协同
很多团队把数据库连接数调大,然后让应用连接池也调大,结果问题依旧。连接池的核心作用是复用连接,而不是让应用直接创建大量物理连接。正确的做法是让连接池的最大连接数小于数据库的max_connections,预留10%到20%的余量给管理操作和应急查询。例如数据库max_connections设为500,应用连接池总和控制在400以内,剩下的100个连接留给DBA手动排查或备份任务。
连接池还需要配置合理的超时参数。如果应用获取连接的超时时间设置过长,高峰期请求会堆积在应用线程中,数据库连接却处于空闲等待状态。建议将连接获取超时设置为2到5秒,超时后快速失败并返回降级响应,而不是让请求无限等待。同时开启连接池的空闲连接检测,定期清理超过30分钟未使用的连接,避免数据库端出现大量Sleep状态的僵尸会话。
防爆破与异常连接阻断
连接数限制在防密码爆破场景中需要配合失败次数限制。MySQL的max_connect_errors虽然能阻断连续失败的IP,但阈值设置不当会导致正常用户在输错几次密码后长时间无法连接。更精细的做法是使用数据库审计插件或中间件记录认证失败日志,通过外部脚本分析日志,对失败次数超过阈值的IP在防火墙层临时封禁。这种方式不会影响数据库自身的连接处理性能,也能避免误伤。
PostgreSQL可以在pg_hba.conf中使用hostssl强制SSL连接,减少明文密码在网络上被截获的风险。同时结合log_connections和log_disconnections记录连接生命周期,分析是否存在异常频繁的连接建立和断开行为。对于慢速连接攻击,可以在操作系统层设置TCP连接建立的速率限制,或者使用SYN Cookie机制缓解半开连接攻击。
监控与告警是限制策略的闭环
设置连接数限制后,必须配套监控指标和告警阈值。关键指标包括当前连接数、历史最大连接数、连接使用率、单账号连接数分布和连接等待时间。当连接使用率超过80%时发出预警,超过90%时立即告警。MySQL可以通过SHOW GLOBAL STATUS LIKE 'Threads_connected'获取当前连接数,通过performance_schema.accounts表查看各账号的连接分布。
PostgreSQL的pg_stat_activity视图提供了详细的会话信息,包括连接来源、状态、当前查询和连接时长。可以定期执行查询,找出持续时间超过1小时的空闲连接,或者来自非业务网段的异常连接。对于连接数突增的情况,需要保留现场信息,包括当时的连接快照、应用日志和网络流量,以便事后分析是应用发布导致还是外部攻击。
连接数限制的常见误区和调优建议
一个常见误区是认为连接数越大越好。数据库的并发处理能力受限于CPU核数、内存和磁盘I/O,盲目调大max_connections会导致上下文切换频繁,整体吞吐量反而下降。MySQL的InnoDB引擎在连接数过多时,内部锁竞争加剧,可能出现连接数很高但查询响应极慢的情况。正确的做法是通过压测找到数据库的最佳并发区间,将连接数控制在该区间内。
另一个误区是只限制全局连接数,不限制单账号连接数。如果某个报表账号执行了一条全表扫描的慢查询,同时应用不断重试建立新连接,这个账号可能占满所有连接,导致核心交易无法执行。为不同优先级的账号设置不同的连接上限,配合资源组或资源调控器限制CPU和内存,才能实现真正的资源隔离。
调优时建议先从应用层连接池入手,确保连接复用率足够高,再调整数据库参数。对于MySQL,可以适当降低wait_timeout和interactive_timeout,让空闲连接尽快释放。对于PostgreSQL,考虑使用PgBouncer的事务池模式,将大量应用连接映射到少量数据库连接上。同时定期检查连接泄漏问题,应用代码中必须确保连接在finally块中关闭,避免异常路径导致连接无法归还连接池。
连接数限制防护策略最终要落到“可观测、可控制、可恢复”三个目标上。可观测是指任何时候都能快速定位当前连接被谁占用、来自哪里、在执行什么操作。可控制是指当连接数异常时,能够快速限制来源或账号,甚至强制断开指定连接。可恢复是指预留足够的连接余量,保证DBA在紧急情况下能够登录数据库执行排查和恢复操作。只有把限制策略和监控、自动化响应结合起来,才能真正抵御连接层攻击和异常流量。
