确认Apache运行Prefork MPM应先执行httpd -V或apache2ctl -V查看MPM行,显示prefork即正确;若为event或worker,须先禁用对应模块再启用mpm_prefork。

如何确认当前Apache运行的是Prefork MPM
直接看进程模型比猜配置更可靠:httpd -V 或 apache2ctl -V 输出里找 MPM 行,如果显示 prefork 就对了;如果看到 event 或 worker,说明当前不是Prefork,改配置前得先停掉其他MPM。
常见错误是只改了 mpm_prefork.conf 却没禁用 mpm_event 模块——Linux发行版(如Ubuntu/Debian)默认启用 mpm_event,它会覆盖Prefork配置。检查是否加载了冲突模块:apache2ctl -M | grep mpm,输出里只能有 mpm_prefork_module,不能同时存在 mpm_event_module 或 mpm_worker_module。
在Debian/Ubuntu上启用Prefork并禁用Event
Debian系把MPM做成独立可切换的包,不能靠改配置文件生效:
- 运行
a2dismod mpm_event(或mpm_worker) - 运行
a2enmod mpm_prefork - 重启服务:
systemctl restart apache2
不执行 a2dismod 直接改 /etc/apache2/mods-enabled/mpm_prefork.conf 是无效的——模块没启用,配置压根不加载。CentOS/RHEL 略不同:需编辑 /etc/httpd/conf.modules.d/00-mpm.conf,注释掉 LoadModule mpm_event_module,取消注释 LoadModule mpm_prefork_module。
调整Prefork关键参数避免崩溃或性能卡死
Prefork用多进程、每个进程单线程,适合PHP + 传统扩展(如Oracle OCI8、某些老版MySQL扩展),但参数设错会导致内存爆满或并发上不去:
-
StartServers别设太高(如32),冷启动时就拉起太多进程,空耗内存 -
MaxRequestWorkers是硬上限,值 =总可用内存 / 每个httpd进程平均内存;用ps aux --sort=-%mem | grep httpd | head -5看几个进程的RSS值取中位数估算 -
MaxConnectionsPerChild设为10000左右较稳妥;太小(如100)导致频繁fork,太大(0或100000)可能累积内存泄漏
改完必须运行 apachectl configtest 验证语法,再 systemctl reload apache2(reload比restart更安全,连接不中断)。
为什么Prefork仍可能加载线程不安全库失败
即使MPM是Prefork,如果模块本身是线程安全编译的(比如某些PHP-FPM SAPI混用场景),或Apache启用了 mod_php 以外的嵌入式解释器(如 mod_python 旧版本),依然可能触发全局符号冲突。
最易被忽略的一点:LD_PRELOAD 或系统级 libmysqlclient 版本与PHP扩展不匹配,会导致 segmentation fault 在子进程中静默退出。查日志看 /var/log/apache2/error.log 是否有 child pid XXX exit signal Segmentation fault ——这时要统一用 mysqlnd 替代 libmysqlclient,或确保所有扩展都静态链接同版本C库。

















