解决子站网盘下载时主站卡死的问题

发布于 2026-02-24  242 次阅读


省流:减少了mysql的最大并发量,减轻了这部分导致的服务器负担,根本问题貌似并没有解决(((。至少现在不卡了。

​ 测试网盘的时候出现了一点比较奇怪的问题(,从网盘下载文件时服务器负载一度会飙升到100%卡的我啥也打不开,连面板都动不了。但是直接从服务器上下载网站备份文件时却又几乎不提升负载。

​ 看看为什么下个东西负载会这么大。用阿里云远程连接一下服务器,看一下基本情况:

  • top 命令显示负载平均值(load average)持续超过 10,而 CPU 空闲率高达 99%;
  • vmstat 输出中 wa(I/O 等待)一度超过 50%,b 列出现大量不可中断睡眠进程;
  • free -h 显示物理内存尚有 1.5GB 空闲,但 swap 使用量却高达 500MB 以上;
  • 网站后台操作时频繁出现 502/504 错误,网盘文件传输时响应变慢。

​ 看来负载高时 CPU 大部分时间空闲,但 I/O 等待显著,且存在大量 D 状态(不可中断睡眠)进程,这通常意味着进程在等待磁盘 I/O 完成。同时,swap 的持续读写(si/so 列)进一步印证了内存与磁盘之间的交换活动频繁。

​ 不对!内存还剩1.5G的空闲,没事调用磁盘干嘛,没有这个必要。使用 ps aux | awk '$8=="D" {print}' 查看 D 状态进程,发现主要为 php-fpm 和 mysqld。进一步通过 /proc/*/status 检查各进程的 swap 占用,发现 mysqld 占用了约 270MB swap,宝塔面板和宝塔定时任务 等也占用了一定量的 swap。这说明虽然物理内存尚有富余,但部分进程的内存页被交换到了磁盘,导致访问这些内存时触发磁盘 I/O。

​ 查看相关配置,发现MySQL 配置中 innodb_buffer_pool_size 仅为 128MB,这说明并不是mysql主动占用导致swap。然而swappiness 值为默认的 60,导致内核倾向于将不常访问的内存页 swap out 以腾出空间给文件缓存,即使物理内存还有空闲。将该值设置为10,再次进行负载测试,效果不明显,仍然达到95%以上。

​ 为了强制删除swap中残留的数据,执行 sudo swapoff -a && sudo swapon -a将服务重启。之后查看状态,在刚刚重启时确实归零了,但在一分钟后swap占用重新来到500MB。整个过程中内存占用保持在15%以下,绝对充足。

​ 这就奇怪了,swap 为什么会迅速重新填满?说明系统确实在主动将内存页换出,而不是历史残留。再次检查进程 swap 占用,发现 mysqld 仍然是头号大户,占据了 270MB 左右。看来问题又回到 MySQL 身上。既然 innodb_buffer_pool_size 只有 128MB,那 MySQL 还能从哪里吃掉这么多内存?看看其他参数。

SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'sort_buffer_size';
SHOW VARIABLES LIKE 'join_buffer_size';
SHOW VARIABLES LIKE 'tmp_table_size';
  • max_connections = 500(?)
  • sort_buffer_size = 786432
  • join_buffer_size = 262144
  • tmp_table_size = 33554432
问题出现了。每个连接虽然实际使用的不多,但 MySQL 会为 最多 500 个并发连接 预留缓冲区。粗略估算,仅 per-thread 内存就可能达到 500 * (768K+256K) ≈ 500MB,再加上 innodb_buffer_pool、临时表等,总内存轻松超过 1.8GB。虽然实际活跃连接很少(Max_used_connections 只有 19),但 MySQL 的内存分配机制仍然会导致内存压力,内核不得不把部分页面换出到 swap。而这台 1.8GB 内存的小服务器根本扛不住 500 个连接的内存预留。难怪 swap 总是填满。

改文件:

sudo vim /etc/my.cnf,将 max_connections 从 500 改为 100,同时适当调小 per-thread 缓冲区:

max_connections = 100
sort_buffer_size = 256K
join_buffer_size = 128K
read_buffer_size = 128K
read_rnd_buffer_size = 256K

重启 MySQL:

sudo systemctl restart mysqld

​ 重启后再次观察 使用free -h查看swap 占用,mysqld 的 swap 从 270MB 逐渐降到 128MB,其他进程的 swap 也陆续减少。再执行一次 sudo swapoff -a && sudo swapon -a 彻底清空,这次 swap 再也没有反弹——一直稳稳地停在 0。负载也彻底恢复正常.

​ 重新尝试用外链下载网盘文件,swap开始上升,CPU占用一度达到80%,但整个过程中负载最高也才60%。暂停下载后,负载慢慢回到11,swap回到110Mb后基本不动,属于Linux 内存管理在压力下的典型表现。

​ 到此算是(?)解决了问题,针不戳啊针不戳🥰🥰🥰


"Hasta Ia Victoria Siempre"