MariaDB errno2002连接失败求助:繁忙服务器偶发资源不可用
问题场景
我们在Debian 12专用服务器(64GB内存,已分配约19GB)上运行MariaDB 11.3.2和PHP-FPM 8.3.12,偶发出现毫秒级的PHP连接报错:
Database connection failed with errno 2002 due to Resource temporarily unavailable
对应的Nginx错误日志:
2024/10/04 02:06:32 [error] 899410#899410: *566044078 FastCGI sent in stderr: "PHP message: Database connection failed with errno 2002 due to Resource temporarily unavailable" while reading response header from upstream, client: xxx, server: xxx.com, request: "POST /xxx.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9003", host: "xxx.com"
已配置MariaDB的log_warnings=4,但问题发生时log_error无相关记录,Netdata监控也未显示明显资源瓶颈或流量激增,需定位问题根源。
排查步骤
一、TCP连接层面的瞬时阻塞排查
- 检查系统TCP监听队列参数:执行
sysctl net.core.somaxconn,默认值128在高并发场景下容易溢出,建议调至1024以上(sysctl -w net.core.somaxconn=1024并写入/etc/sysctl.conf持久化)。同时确认MariaDB的max_connections与PHP-FPM的pm.max_children匹配,避免PHP侧发起的连接数瞬间超过MariaDB监听队列上限。 - 实时监控MariaDB监听队列:执行
ss -ltnp | grep mariadb,观察Send-Q列,若出现非零值说明监听队列已满,是连接失败的直接原因。 - 检查TIME_WAIT连接复用:执行
sysctl net.ipv4.tcp_tw_reuse,确保值为1,避免大量TIME_WAIT状态的连接占用端口,导致无法新建连接。
二、MariaDB内部连接处理限制排查
- 检查线程缓存配置:执行
SHOW GLOBAL STATUS LIKE 'Threads_created';,若该值每秒增长超过10,说明thread_cache_size不足,新建连接时需频繁创建线程导致短暂阻塞。建议将thread_cache_size设置为max_connections/4左右,重启MariaDB生效。 - 验证连接错误阈值:执行
SHOW GLOBAL STATUS LIKE 'Max_connect_errors';,若接近max_connect_errors设置值,可能触发连接拦截,但此场景通常会有日志,可临时调大该值测试。 - 检查InnoDB并发限制:执行
SHOW ENGINE INNODB STATUS;,查看TRANSACTIONS部分是否有大量等待线程,若innodb_thread_concurrency设置过低,可能导致新连接被暂时拒绝。
三、PHP-FPM与系统资源冲突排查
- 检查文件描述符上限:执行
ulimit -n查看系统全局文件描述符上限,对比MariaDB的SHOW GLOBAL STATUS LIKE 'Open_files';和PHP-FPM进程的lsof -p <php-fpm主进程PID> | wc -l,若任一数值接近上限,会导致无法新建连接。需调大/etc/security/limits.conf中的nofile参数。 - 优化PHP连接方式:若使用短连接,高并发下会频繁创建销毁连接,建议切换为持久连接。同时检查PHP配置中的
mysql.allow_persistent=On、mysql.max_persistent(建议设置为MariaDBmax_connections的70%左右),避免持久连接数超限。 - 调整PHP-FPM进程数:确保
pm.max_children不超过系统可承载的进程数(按内存估算:单PHP进程内存×max_children ≤ 剩余可用内存),避免进程激增导致系统资源耗尽。
四、系统层面瞬时波动排查
- 检查系统日志:查看报错时间点的
/var/log/syslog和/var/log/kern.log,确认是否有OOM Killer触发、磁盘IO瞬时飙升(如备份、快照任务)、CPU软中断过高等情况,这些都可能导致连接处理延迟。 - 内核性能采样:在高峰时段执行
perf top,观察是否有网络相关内核函数(如tcp_v4_do_rcv)占用过高CPU,导致TCP连接处理缓慢。 - 中断请求分配:确认
irqbalance服务正常运行(systemctl status irqbalance),避免网络中断请求集中在单个CPU核心,导致核心过载。
五、MariaDB日志有效性排查
- 验证日志配置:执行
SHOW VARIABLES LIKE 'log_error';确认日志路径正确,检查路径权限(确保mysql用户有写入权限:ls -l <log_error路径>)。 - 临时开启通用日志:在低峰时段执行
SET GLOBAL general_log = ON;,捕捉报错时间点的连接请求,排查是否有异常连接行为。用完后及时关闭(SET GLOBAL general_log = OFF;)避免性能影响。 - 确认log_warnings生效:执行
SHOW VARIABLES LIKE 'log_warnings';,若值不为4,需修改my.cnf后重启MariaDB。
内容的提问来源于stack exchange,提问作者Alexey Ozerov
相关产品推荐
相关产品推荐

