先看现象。前台开始成片报 502,MySQL 错误日志里全是 Too many connections。程序每个请求新开一个连接,蜘蛛并发一上来就把连接数顶到上限。
排查方向其实有限,先把可能性排一排。应用每个请求新建连接,用完不主动释放。少数情况下是max_connections 只有 150,与 FPM 进程数不匹配。
还有一种情况,慢查询占着连接不放,队列越排越长。
另外,没有连接池,突发并发直接顶穿上限。
第一件事是看当前连接数与上限
mysql -e 'show status like "Threads_connected"; show variables like "max_connections";'
再往下抓出占连接最久的语句
mysql -e 'select id,time,state,info from information_schema.processlist order by time desc limit 10;'
然后把上限调到与进程数匹配并接上连接池
SET GLOBAL max_connections = 500;
给慢查询补索引并设语句超时
手上没有现成的复现脚本,就照着线上请求手工拼了一个。
恢复的判定其实很直接。连接数稳定在两百以内,502 不再出现,蜘蛛抓取成功率回到九成九,慢查询条数同步下降。
调大上限只是缓兵之计,连接泄漏不修,调到一千也会在某个高峰被打满。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
