本文针对 Linux 系统中出现的 kernel:NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s+ 报错,详细解析错误本质、核心触发原因,提供“紧急急救→根源排查→永久解决→预防优化”全流程方案,重点适配 Docker 部署 SpringBoot + MySQL + Nginx 多服务场景,解决服务器 CPU 卡死、进程无响应、系统卡顿等问题,适用于虚拟机、轻量云服务器、物理机等各类 Linux 环境。
一、报错还原与核心解读
1.1 报错完整信息
Message from syslogd@localhost at May 4 06:52:17 ...
kernel:NMI watchdog: BUG: soft lockup - CPU#1 stuck for 24s! [connection:3853]
Message from syslogd@localhost at May 4 07:00:23 ...
kernel:NMI watchdog: BUG: soft lockup - CPU#1 stuck for 21s! [connection:3853]
Message from syslogd@localhost at May 4 07:23:50 ...
kernel:NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [connection:3853]
1.2 错误本质(一句话看懂)
soft lockup(软锁死):Linux 内核的 NMI watchdog(看门狗)检测到某个 CPU 核心被进程占用超过 20 秒(默认阈值),无法执行其他任务,判定为“卡死”,触发内核报警。这是 服务器级严重故障,非应用报错,若不及时处理,会导致服务器卡顿、无响应、甚至自动重启。
1.3 关键报错字段解读
-
CPU#1 stuck for 22s:CPU 1 号核心被卡死 22 秒(阈值可配置,默认 20 秒),核心无法响应内核调度。 -
[connection:3853]:卡死 CPU 的进程信息(3853 是进程 PID,connection 对应 Java 项目的数据库连接进程)。 -
[scsi_eh_2:301]:磁盘 IO 相关进程(301 是 PID),说明可能伴随磁盘 IO 卡死,多出现于虚拟机/云服务器。
二、核心触发原因(结合 Docker 多服务场景)
结合你当前部署的 Docker + SpringBoot + MySQL + Nginx 环境,报错的核心原因可归纳为 3 点(按优先级排序),90% 的场景都是前两点导致:
2.1 最常见:CPU 资源不足 + 高负载进程占用
这是你场景下的直接原因:
-
服务器配置过低(如 1 核 2G、2 核 2G),同时运行 Docker 容器(MySQL、Redis、Nginx)+ Java 项目,CPU 长期处于 100% 占用状态。
-
Java 项目中存在低效 SQL(如你之前遇到的 GROUP BY 无索引、全表扫描 + 多表联查),触发大量 CPU 计算,直接卡死 1 号核心。
-
报错中的
connection:3853正是 Java 项目的数据库连接进程,证明是 Java 应用占用 CPU 导致卡死。
2.2 次要原因:磁盘 IO 异常(虚拟机/云服务器常见)
报错中的 scsi_eh_2:301 对应磁盘 IO 进程,说明可能存在:
-
虚拟机磁盘挂载异常、IO 读写速度过慢(如机械硬盘、云服务器低配置磁盘)。
-
Docker 容器挂载目录权限不足、磁盘空间满,导致 IO 阻塞,间接拖死 CPU。
2.3 其他原因(少见)
-
Linux 内核版本过低/存在漏洞,导致 watchdog 误报或真死锁(如 CentOS 7 部分旧内核)。
-
硬件问题(物理机):CPU 过热、内存故障,导致核心无法正常工作。
-
Docker 容器内存/CPU 限制不合理,导致进程抢占资源异常。
三、紧急急救方案(立即解决服务器卡死,优先执行)
当服务器出现上述报错时,已处于“半卡死”状态,需立即执行以下步骤,避免服务器彻底崩溃、无法连接:
3.1 第一步:强制终止高负载进程(快速释放 CPU)
-
登录服务器(若 SSH 连接卡顿,可通过云服务器控制台/VNC 登录),执行命令查看 CPU 占用情况:
# 按 CPU 占用率排序,查看前 10 个高负载进程top -o %CPU# 或直接查看报错中的 PID(如 3853)ps -ef | grep 3853 -
终止高负载进程(优先终止 Java 进程、异常 Docker 容器):
# 强制终止报错中的进程(PID 3853,根据实际 PID 修改)kill -9 3853# 若无法确定具体 PID,终止所有 Java 进程(临时应急)kill -9 $(ps -ef | grep java | grep -v grep | awk '{print $2}')# 停止所有 Docker 容器(释放 CPU/IO 资源)docker stop $(docker ps -aq)
3.2 第二步:重启服务器(彻底释放资源)
终止进程后,服务器可能仍有残留负载,建议重启服务器,彻底恢复 CPU/IO 正常状态:
reboot
⚠️ 注意:生产环境需提前告知业务,避免数据丢失;测试环境可直接重启。
3.3 第三步:验证急救效果
服务器重启后,执行以下命令,确认 CPU 负载正常:
# 查看 CPU 负载(%us 低于 70% 即为正常)
top
# 查看系统日志,确认无 soft lockup 报错
dmesg | grep "soft lockup"

若日志无新的报错,CPU 负载正常,说明急救成功。
四、永久解决方案(从根源杜绝报错,重点适配你的场景)
急救只能临时解决,要彻底杜绝 soft lockup 报错,需针对“CPU 不足、低效 SQL、IO 异常”三个核心问题,逐一优化:
4.1 优化方案 1:提升服务器配置(最根本)
结合你当前部署的服务(Docker + Java + MySQL + Nginx),建议服务器配置至少为:
-
最低配置:2 核 4G(勉强运行,适合测试环境)
-
推荐配置:4 核 8G(生产环境,稳定运行多服务)
若为云服务器,直接升级配置;若为虚拟机,增加 CPU 核心和内存分配,这是解决“CPU 卡死”最根本的方案。
4.2 优化方案 2:修复 Java 项目低效 SQL(关键步骤)
你之前遇到的 only_full_group_by 报错,对应的 SQL 正是导致 CPU 高负载的核心原因,需优化 SQL 和索引:
-
定位低效 SQL:
# 进入 MySQL 容器,开启慢查询日志(临时开启)docker exec -it mysql8 mysql -uroot -p123456set global slow_query_log=1;set global long_query_time=2; # 执行时间超过 2 秒的 SQL 记录为慢查询show variables like 'slow_query_log'; # 确认开启慢查询日志路径:/mydata/mysql/data/xxx-slow.log,查看日志找到耗时最长的 SQL(即之前的 GROUP BY 联查 SQL)。 -
优化 SQL 和索引:
-
针对 GROUP BY 字段(如
id)添加索引 -
优化联查 SQL:减少不必要的联表,避免全表扫描;SELECT 字段只查询需要的字段,不使用
p.*。
-
4.3 优化方案 3:Docker 容器资源限制(避免进程抢占资源)
给 Docker 容器设置 CPU/内存限制,避免单个容器(如 Java 项目、MySQL)占用全部 CPU 资源,导致服务器卡死:
-
停止现有容器,重新启动时添加资源限制参数(以 Java 项目、MySQL 为例:
docker run -d \
--name mysql8 \
--restart always \
--network shop-network \
--cpus 1 \ # 限制 CPU 核心数
-m 1g \ # 限制内存使用
-p 3306:3306 \
-v /mydata/mysql/conf:/etc/mysql/conf.d \
-v /mydata/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
# 启动 Java 项目容器,限制使用 1-2 核 CPU、2G 内存
docker run -d \
--name shop \
--restart always \
--network shop-network \
--cpus 2 \
-m 2g \
-p 8113:8113 \
-e MYSQL_HOST=mysql8 \
-e REDIS_HOST=redis \
shop:1.0
-
参数说明:
-
--cpus 1:限制容器最多使用 1 核 CPU。 -
-m 1g:限制容器最多使用 1G 内存,避免内存溢出拖死 CPU。
-
4.4 优化方案 4:磁盘 IO 优化(解决 scsi_eh_2 报错)
针对报错中的 scsi_eh_2:301 磁盘 IO 问题,优化如下:
-
检查磁盘空间,避免磁盘满导致 IO 阻塞:
# 查看磁盘使用情况df -h# 若磁盘使用率超过 80%,清理无用文件(如 Docker 日志、旧镜像)# 清理 Docker 无用镜像和容器docker system prune -a -f# 清理 MySQL 日志(若日志过大)rm -rf /mydata/mysql/logs/*.log -
优化 Docker 挂载目录权限(避免 IO 读写权限不足):
# 给所有挂载目录授权chmod -R 777 /mydata/mysqlchmod -R 777 /mydata/redischmod -R 777 /mydata/nginx -
云服务器/虚拟机优化:将磁盘升级为 SSD(提升 IO 读写速度),避免使用机械硬盘。
4.5 优化方案 5:调整 Linux 内核参数(可选,辅助优化)
若服务器仍偶尔出现报错,可调整内核 watchdog 阈值,延长检测时间(不推荐关闭 watchdog,保留故障检测功能):
-
编辑内核配置文件:
vi /etc/sysctl.conf -
添加以下配置(将 watchdog 阈值从 20 秒改为 60 秒):
# 调整 NMI watchdog 检测阈值(单位:秒)kernel.watchdog_thresh = 60 -
生效配置:
sysctl -p
五、验证优化效果(确保彻底解决)
优化完成后,启动所有服务,执行以下步骤验证:
-
启动服务:
docker start mysql8 redis nginx -
查看 CPU 负载,确保长期稳定在 70% 以下:
top # 持续观察 5-10 分钟 -
查看系统日志,确认无 soft lockup 报错:
dmesg | grep "soft lockup"journalctl -u syslog | grep "soft lockup" -
测试 Java 项目接口,执行之前的慢查询 SQL,确认无卡顿、无报错。
若以上步骤均无异常,说明优化成功,后续不会再出现 soft lockup 报错。
六、常见问题排查(避坑指南)
6.1 重启服务器后,报错依旧
原因:未优化低效 SQL 或服务器配置仍不足。
解决:优先升级服务器配置,再优化 SQL 和索引;若无法升级配置,暂时停止部分非必要服务(如 Nginx 可暂时关闭,测试 Java 项目是否正常)。
6.2 终止 Java 进程后,CPU 仍高负载
原因:MySQL 进程占用过高(如慢查询未优化)。
解决:进入 MySQL,终止慢查询进程: show processlist; # 查看正在执行的进程 kill 进程ID; # 终止慢查询进程
6.3 磁盘空间充足,但仍有 scsi_eh_2 报错
原因:磁盘 IO 速度过慢或挂载异常。
解决:升级 SSD 磁盘;检查虚拟机挂载配置,重新挂载磁盘。
七、总结
核心结论
本次 kernel:NMI watchdog: BUG: soft lockup 报错,本质是 服务器 CPU 资源不足 + Java 项目低效 SQL 导致 CPU 卡死,伴随磁盘 IO 异常加剧故障。
解决流程(优先级排序)
-
紧急急救:终止高负载进程 → 重启服务器,快速恢复服务。
-
根源优化:升级服务器配置(2 核 4G 以上)→ 优化低效 SQL 和索引。
-
辅助优化:限制 Docker 容器资源 → 优化磁盘 IO → 调整内核参数。
-
验证效果:观察 CPU 负载 + 系统日志,确认无报错。
预防措施
-
定期检查服务器 CPU、磁盘、内存使用情况,避免资源耗尽。
-
开发阶段优化 SQL,避免全表扫描、无索引分组查询。
-
给 Docker 容器设置资源限制,避免单个进程抢占全部资源。
-
定期清理服务器无用文件、Docker 旧镜像,释放磁盘空间。
通过以上方案,可彻底解决 soft lockup 报错,确保 Docker + Java + MySQL 多服务稳定运行,适用于测试环境和生产环境,新手可直接按步骤操作,无需复杂的内核知识。

8019

被折叠的 条评论
为什么被折叠?



