mysql上不了服务器,第一反应不是看mysql日志,而是立刻登录服务器查CPU使用率
当mysql服务无法连接时,绝大多数情况下是服务器CPU被某个进程打满,导致mysqld根本没有机会响应请求。 你需要先用SSH登录服务器,执行top命令看整体负载,再按CPU排序找出占用最高的进程,顺着这个进程去定位问题,整个过程不超过两分钟,比盲目重启mysql有效得多。
下面我把这套排查逻辑拆开讲透,每一步都给你可执行的命令,你照着做就行。
mysql连接不上怎么查服务器cpu使用率:先分清是“假死”还是“真满”
很多朋友遇到mysql上不去,第一反应是看mysql的错误日志,或者直接重启mysql服务,但你要知道,如果CPU已经被其他进程吃干榨净,mysql进程本身是正常启动的,它只是“抢不到”CPU时间片,所以表现为连接超时或者拒绝连接,这时候你重启mysql也没用,因为CPU依然忙不过来。
判断CPU使用率是第一步,也是最重要的一步,进入服务器的SSH终端,先执行:
top
这个命令会实时刷新进程列表,你需要看两个关键区域:
- 顶部负载均值:
load average后面的三个数字,分别代表1分钟、5分钟、15分钟的系统负载,如果这三个数字都明显超过CPU核心数,说明系统已经处于过载状态,比如你的服务器是2核,负载达到4以上,那就很紧张了。 - 进程列表的%CPU列:按
P键(大写P),进程会按CPU占用率从高到低排序,这时候一眼就能看到是谁在疯狂消耗CPU。
如果top命令本身卡住不动,或者执行后没有任何输出,可能连SSH都受影响,那就需要通过云服务商的控制台VNC登录,或者直接重启服务器后再排查,但多数情况下SSH还能进,只是慢。
找准吃CPU的“凶手”:用top和ps命令锁定进程
先看mysqld本身有没有异常
在top界面按P排序后,观察mysqld进程的CPU占用率,正常情况下,一个空闲或低负载的mysql进程,CPU占用一般不会超过10%,如果mysqld自己占了100%或更高,那问题大概率出在SQL语句、索引失效或者连接数爆炸上。
这时候你就要进入mysql命令行(前提是还能挤得进去,如果连不上就跳过这步),执行:
SHOW FULL PROCESSLIST;
这个命令会列出所有正在执行的SQL,重点看
Time列和Info列,有没有长时间不结束的查询,有没有大量Sleep状态的空闲连接,如果有成百上千个连接,就算什么也不干,也会消耗内存和CPU上下文切换的开销。
如果不是mysqld,看看是不是其他进程在搞鬼
常见的“CPU大胃王”有这几种:
- 网站爬虫或恶意攻击:比如大量的HTTP请求打到nginx或者Apache上,导致web服务进程忙死。
- 备份任务或定时任务:比如凌晨3点的数据库备份脚本,压缩大文件时CPU飙高,恰好撞上你连接mysql的时间点。
- 挖矿病毒:近年来这种情况不少见,服务器被植入挖矿程序,CPU长期处于高位,进程名可能伪装成
kworker、systemd或随机字符串。 - 内存不足触发Swap风暴:内存不够时系统疯狂换页,CPU忙于处理磁盘I/O,也会表现为CPU使用率极高。
用top找到可疑PID后,再用ps命令确认细节:
ps -ef | grep <PID>
或者看这个进程的所有线程:
top -H -p <PID>
如果你发现某个进程完全陌生,而且CPU占用夸张,先别急着杀,用lsof -p <PID>或者ls -l /proc/<PID>/exe看看这个进程的可执行文件路径在哪里,如果是/tmp或者/var/tmp下的文件,大概率是入侵行为,建议直接kill掉然后立刻检查系统安全。
mysql无法连接但服务器CPU高?按这几个场景对号入座
CPU满,mysqld本身占用不高
这种情况最常见,CPU被php-fpm、java应用或者redis等其他服务占满,mysql虽然活着,但拿不到足够的CPU时间去处理新连接,这时候你不需要动mysql,而是去优化那个占CPU的应用,比如php-fpm的进程数设置得太高,或者代码里有死循环。
操作建议:/etc/init.d/php-fpm restart 或者重启对应的应用服务,让CPU降下来,mysql自然恢复,如果这类情况经常出现,考虑给应用和数据库分服务器部署,或者限制单个服务的CPU配额。
mysqld进程CPU占用接近100%
说明是mysql内部的问题,最常见的几个原因:
- 慢查询堆积:一个表没有索引,全表扫描几百万行数据,多个这样的查询同时进来,CPU瞬间打满。
- 连接数飙升:应用连接池配置错误,或者接口被刷,导致mysql需要处理大量短连接,频繁创建和销毁线程非常耗CPU。
- 临时表空间不够:排序或分组操作使用了磁盘临时表,产生大量磁盘I/O,但也会反噬CPU。
排查思路:进入mysql执行SHOW GLOBAL STATUS LIKE 'Threads_connected';看当前连接数,如果远高于正常值,追查应用侧是不是有并发bug,用SHOW FULL PROCESSLIST;看是否有多个同样的SQL在跑,如果有,那就是SQL优化问题。
CPU和负载都正常,但mysql还是连不上
这种情况就不能怪CPU了,你要检查的是端口监听和防火墙,执行:
netstat -ntlp | grep 3306
确认mysqld是否在监听3306端口,如果没输出,说明mysql进程没起来,看错误日志,如果有监听,再检查防火墙规则:
iptables -L -n | grep 3306
同时也要想到云安全组,很多简米云或酷番云的服务器,安全组规则改了之后会阻止外网访问3306端口,这时候CPU使用率再低也没用,因为网络层面不通。
用mysqladmin或sysbench做压力测试,判断CPU瓶颈边界
如果你怀疑自己的服务器配置已经跑不动现有的业务负载,可以用工具模拟一下压力,行业共识认为,在压测之前要先摸清CPU的基准能力,比如用sysbench做一个简单的CPU测试:
sysbench cpu --threads=4 --time=30 run
看每秒可以处理多少事件,如果数字很低,说明CPU本身性能不佳,或者被云服务商限流了。
另一个更贴近mysql的手段是mysqladmin命令,只要mysql能连上(哪怕很慢),执行:
mysqladmin -u root -p extended-status
观察Threads_running和Questions这两个值。Threads_running如果长期大于CPU核数,说明系统正在排队处理查询,CPU已经不够用,这时候加索引、优化SQL比加服务器内存更有效。
几个必须养成的“CPU体检”习惯,避免再次上不了服务器
- 日常监控必须做:别等到连不上才去看,用
htop或者nmon这类工具,或者云服务商的监控面板,设置CPU报警阈值,比如持续5分钟超过80%就报警。 - 定期看慢查询日志:mysql的
slow_query_log开启,然后定期分析里面的SQL,把long_query_time设为2秒,把超过2秒的查询都揪出来优化。 - 控制应用连接数:连接池最大连接数设成合理的值,比如50或100,别让应用无限创建连接,同时在mysql侧设置
上限,双保险。max_connections
- 隔离业务高峰期:比如每天上午10点有批量报表任务,可以把时间改到凌晨。
Q&A:mysql上不了服务器时,关于CPU使用的三个常见疑问
问:mysql连接直接被拒绝,但top显示CPU只有20%,为什么还会连不上?
答:如果CPU空闲,网络也通,那问题在mysql自身,执行SHOW VARIABLES LIKE 'max_connections';看连接数上限,再用SHOW GLOBAL STATUS LIKE 'Max_used_connections';看历史最大连接数,如果连接数打满,mysql会直接拒绝新连接,报“Too many connections”错误,解决办法是临时调大max_connections,或者用kill命令清理空闲连接,但根本解法是优化应用侧连接池。
问:查看CPU使用率时,load average很高但CPU却显示100%,这两个指标有什么区别?
答:load average是运行队列中等待CPU调度的进程数量,它包含不可中断的睡眠进程(比如等待磁盘I/O),CPU使用率反映的是CPU处于忙碌状态的百分比,两者不完全同步,比如大量进程在等待磁盘读写时,CPU可能只有60%,但load average已经飙到10,这种情况下,问题可能出在磁盘I/O瓶颈,而不是CPU算力不足,你需要用iostat -x 1看磁盘的%util值,如果接近100%,就说明磁盘拖累了整体性能,mysql的上不了服务器并不是CPU直接造成的。
问:服务器CPU被mysql占满,我用kill -9杀掉了mysqld进程,然后重启,CPU还是满的,为什么?
答:因为你杀掉的是mysql进程,但导致CPU占满的可能是其他原因,比如外部刷接口的流量、无限递归写的存储过程,或者你重启后所有积压的查询又开始重新执行,正确做法是重启前先用SHOW FULL PROCESSLIST;记录下所有查询,然后一个一个KILL那些异常的线程ID,同时检查应用代码,看是否有循环调用的bug,如果杀完mysql后CPU依然高,用top再看一眼到底是谁在占用,很可能是一个独立的PHP进程或Java进程在作怪,和mysql无关。
总结下来,mysql上不了服务器别慌,用top命令看一眼CPU使用情况,多数问题在20分钟内都能找到方向,要么是CPU被占满导致mysqld饿死,要么是mysql内部查询堵塞,要么是网络层拦截,先看CPU,再查进程,最后动SQL,这个顺序不会错。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/610251.html




