Linux查看进程占用内存最高,kill进程方法
前言
服务器内存吃紧、Swap被刷爆,往往是某个程序内存泄漏或卡死进程占着不放。要先找到"谁在吃内存",确认后再决定是优雅重启还是直接kill。本篇给出从查进程到杀进程的完整命令。
一、按内存占用排序找进程
ps 一次性列出并排序,输出RES(实际物理内存,单位KB):
# 按内存占用从高到低,取前10
ps aux --sort=-%mem | head -10
# 按CPU占用排序
ps aux --sort=-%cpu | head -10
列说明:USER 进程用户、%MEM 内存占比、RSS 实际物理内存、COMMAND 启动命令。
更直观的内存排行:
# 显示内存占用最高的进程,VSZ/RSS单位KB
ps -eo pid,ppid,user,%mem,%cpu,rss,comm --sort=-rss | head
二、用top/htop交互查看
top
# 进入后按 M 按内存排序,按 P 按CPU排序,k 输入PID杀进程,q退出
装个 htop 更清楚:
yum install -y htop
htop
三、按名字批量找进程PID
# 查php-fpm相关进程
pgrep -af php-fpm
# 或
ps -ef | grep php-fpm | grep -v grep
pgrep 只输出PID,-a 带命令行。
四、kill进程(先温柔再强杀)
# 正常结束(SIGTERM=15),给进程清理机会
kill PID
# 按名字结束所有同名进程
killall php-fpm
pkill -f "php think"
# 杀不掉再强制杀(SIGKILL=9),数据可能损坏,最后手段
kill -9 PID
信号优先级:
kill -15(默认):请求退出,进程可捕获;kill -9:直接杀死,无法拦截。
服务类进程优先用它自己的重启命令而不是裸kill:
systemctl restart php-fpm
五、常见坑
- 只看%MEM不看RSS:共享内存会被重复算,判断真实占用看RSS;
- 上来就kill -9:数据库、日志服务强杀可能坏数据,先15再9;
- 杀错进程:杀之前用
ps -p PID -o cmd确认这个PID到底是谁; - 僵尸进程杀不掉:状态
Z的僵尸要杀它的父进程,僵尸本身已经不占CPU只占PID表; - kill完又自动起来:被systemd/守护进程托管,要用
systemctl stop或它的管理命令,否则白杀。
总结
ps aux --sort=-%mem | head 或 top 按M排序找内存大户,确认PID后先用 kill(15)优雅结束,不行再 kill -9。服务类进程优先 systemctl restart,避免强杀造成数据损坏。
遇到问题加QQ23979811 协助处理
MySQL锁表查询,kill锁表进程
前言
网站突然卡死,查什么都慢,可能是表被锁住了。怎么查谁锁的表,怎么杀掉锁表进程?
一、查看正在执行的进程
SHOW FULL PROCESSLIST;
看State列,要是 Locked 就是锁表了。
二、查看锁表信息
查看当前锁
SELECT * FROM information_schema.INNODB_TRX;
这是InnoDB正在执行的事务。
查看锁等待
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
看谁在等谁的锁。
查看具体的锁
SELECT * FROM information_schema.INNODB_LOCKS;
MySQL 8.0改成了 performance_schema.data_locks。
三、找出锁表的SQL
查看长时间运行的事务
SELECT
trx_id,
trx_state,
trx_started,
trx_mysql_thread_id,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) as run_seconds,
trx_query
FROM information_schema.INNODB_TRX
ORDER BY trx_started;
run_seconds 越大,跑的越久,越可能是锁表的元凶。
查看锁等待链
SELECT
r.trx_id as waiting_trx_id,
r.trx_mysql_thread_id as waiting_thread,
r.trx_query as waiting_query,
b.trx_id as blocking_trx_id,
b.trx_mysql_thread_id as blocking_thread,
b.trx_query as blocking_query
FROM information_schema.INNODB_LOCK_WAITS w
JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id
JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id;
四、杀掉锁表进程
找到进程ID
从上面的查询结果里,找到 blocking_thread,就是锁表的那个连接ID。
杀掉进程
KILL 进程ID;
批量杀掉
比如杀掉所有跑了超过60秒的事务:
SELECT CONCAT('KILL ', trx_mysql_thread_id, ';')
FROM information_schema.INNODB_TRX
WHERE TIMESTAMPDIFF(SECOND, trx_started, NOW()) > 60;
把结果复制出来执行。
五、常用查询
查看谁在锁什么表
SELECT
t.table_name,
t.table_rows,
l.lock_type,
l.lock_mode,
l.lock_id,
t2.trx_mysql_thread_id,
t2.trx_query,
t2.trx_started
FROM information_schema.INNODB_LOCKS l
JOIN information_schema.INNODB_TRX t2 ON l.lock_trx_id = t2.trx_id
JOIN information_schema.TABLES t ON l.lock_table = CONCAT(t.table_schema, '/', t.table_name);
查看行锁还是表锁
RECORD是行锁TABLE是表锁
六、为什么会锁表
原因1:大事务没提交
开了个事务,执行了一大堆,一直没commit,锁就一直占着。
解决: 事务要短小,及时提交。
原因2:没有索引
更新/删除没走索引,会锁全表。
解决: 给where条件加索引。
原因3:DDL操作
ALTER TABLE、OPTIMIZE TABLE这些会锁表。
解决: 低峰期做,或者用pt-online-schema-change。
原因4:长查询
一条SQL跑几分钟,锁住相关行。
解决: 优化慢SQL。
七、MySQL 8.0的变化
MySQL 8.0把INNODB_LOCKS和INNODB_LOCK_WAITS废弃了,改成了performance_schema。
查看锁等待(8.0)
SELECT * FROM performance_schema.data_lock_waits;
查看锁(8.0)
SELECT * FROM performance_schema.data_locks;
常见坑
坑1:杀错进程
杀了正在正常执行的业务进程,导致业务报错。
解决: 先看清楚trx_query是什么,确认是僵尸事务再杀。
坑2:杀了又出来
杀了锁表进程,过一会儿又锁了。
原因: 程序里有死循环,或者连接池自动重连了。
解决: 找到源头,修代码。
坑3:KILL不掉
KILL 123;
进程还在,没杀掉。
原因: 事务在做rollback,需要时间。
解决: 等它回滚完,或者直接重启MySQL。
坑4:查不到锁信息
information_schema.INNODB_TRX是空的。
原因: 可能是MyISAM表,MyISAM的表锁不在InnoDB里。
MyISAM表锁查看:
SHOW OPEN TABLES WHERE In_use > 0;
坑5:锁和MDL搞混
MDL(元数据锁)不是行锁,是表结构的锁。
查看MDL锁:
SELECT * FROM performance_schema.metadata_locks;
总结
锁表排查三步:
SHOW FULL PROCESSLIST看有没有Lockedinformation_schema.INNODB_TRX找长事务KILL 进程ID杀掉锁表进程
记住: 杀之前先看清楚是什么SQL,别误杀了正常业务!
遇到问题加QQ23979811 协助处理