PHP的pm、pm.max_requests、memory_limit参数优化说明

本文探讨了PHP性能优化的关键参数,包括php-fpm.conf中的pm和pm.max_requests,以及php.ini中的memory_limit。深入分析了这些参数如何影响服务器性能和内存管理,以及如何设置它们以防止内存溢出和提高处理效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PHP的pm、pm.max_requests、memory_limit参数优化说明

1、php-fpm.conf中的pm

pm是来控制php-fpm的工作进程数到底是一次性产生固定不变(static)还是在运行过程中随着需要动态变化(dynamic)。众所周知,工作进程数与服务器性能息息相关,太少则不能及时处理请求,太多则会占用内存过大而拖慢系统。因为php-fpm处理请求时会随着处理的请求数的增加而占用越来越多的内存,所以static模式下往往不好判断启动的能使内存利用最大化的固定进程数,所以想到了dynamic模式。可是为什么我们不用dynamic模式呢,试想某个时刻请求数比较低,20个进程足够应付,突然压力增大了,出现了40个并发PHP请求,按照最小5个空闲进程的设置就需要45个进程,也就是说需要在短时间内创建出25个进程,我们知道创建进程的操作是比较消耗系统资源的,再加上40个并发PHP请求肯定也会给MySQL带来一定的压力,此时再创建25个进程无疑是雪上加霜,所以我在这里还是选择了static模式。

2、php-fpm.conf中的pm.max_requests

根据说明我们知道这个参数的含义是php-fpm工作进程处理完多少请求后自动重启,主要目的就是为了控制请求处理过程中的内存溢出,使得内存占用在一个可接受的范围内。从这里我们感觉这个数字似乎设置的小一点更加有利于性能提升,但是当这个数字非常小的时候会发生一种情况,由于PHP请求是平均地分配给各个工作进程的,如果这个值太小就会导致所有的工作进程几乎同时达到这个值并且进入需要重启的状态,当所有的工作进程都在同一时刻重启就会发生在数秒内甚至更长的时间PHP将停止响应直到所有的进程均重启完为止。这是不能接受的,所以我一般会把这个值设置为PHP启动后第一批工作进程达到此值需要重启时,第一个进程重启与最后一个进程重启之间的时间相差1分钟以上,一般在压力比较大的晚上这个差值将会扩大到5分钟左右,此时对进程重启对服务器的负面影响就可以忽略了。

3、php.ini中的memory_limit

这个值是用来限制PHP所占用的内存的,具体一点说就是一个PHP工作进程即php-fpm所能够使用的最大内存,默认是128MB,一开始在虚拟机中我设置为PHP 5.1.6的默认值16MB,发现大于16MB的附件将无法下载,也就是说PHP 5.3中附件是从硬盘完整读取到PHP内存中再传给nginx的,这跟PHP 5.1.6+Apache 2.2.3不同,后者读取附件是PHP并不加载这个附件而是直接交给Apache来加载,这就使得php-fpm占用内存大了不少。当php-fpm占用内存达到了memory_limit所限制的值时,当前进程会被fpm主进程使用TERM信号终止掉,此时被处理的PHP请求将返回客户端502错误,nginx的error log中将记录出错原因是“Connection reset by peer”。可是更加令人难以理解的事情发生了,在使用了eAccelerator的PHP 5.3上,居然发生了当php-fpm内存达到memory_limit所限制的值时,所有进程都开始疯狂重启而不再接受任何请求,此时除非使用kill命令杀死主进程,否则php-fpm永远都不会恢复响应,可想而知nginx必然出现无止境的502错误

<think>我们分析一下这个SQL语句: 原始SQL: select c.request_no, t.old_tool_gather_no from mes.tool_check c, mes.tool_note_requests t where c.request_no = t.request_no group by c.request_no 问题:数据库提示“不是group by表达式”。这是因为在GROUP BY子句中,只指定了c.request_no,而SELECT子句中却包含了两个列:c.request_no和t.old_tool_gather_no。 在Oracle中,当使用GROUP BY子句时,SELECT列表中的非聚合列必须全部出现在GROUP BY子句中,或者被包含在聚合函数中。这里,t.old_tool_gather_no既没有出现在GROUP BY子句中,也没有被聚合函数包裹(如MAX, MIN, SUM等),因此Oracle会报错。 解决方案: 有两种方式解决: 1. 将t.old_tool_gather_no也添加到GROUP BY子句中。 2. 如果t.old_tool_gather_no的值对于每个c.request_no是唯一的(或者你想取其中一个值),那么可以使用聚合函数,例如MAX(t.old_tool_gather_no)。 根据你的需求,如果你确定每个c.request_no对应的t.old_tool_gather_no都是相同的(因为c.request_no = t.request_no是一对一关系?),那么你可以将它们都加入到GROUP BY子句中。但如果是多值,那么使用聚合函数可能更合适。 方案1:将两个列都加入GROUP BY ```sql select c.request_no, t.old_tool_gather_no from mes.tool_check c, mes.tool_note_requests t where c.request_no = t.request_no group by c.request_no, t.old_tool_gather_no ``` 方案2:使用聚合函数(例如,取任意一个值,这里用MAX或MIN,或者如果确定唯一,也可以使用MAX或MIN,因为结果一样) ```sql select c.request_no, max(t.old_tool_gather_no) as old_tool_gather_no from mes.tool_check c, mes.tool_note_requests t where c.request_no = t.request_no group by c.request_no ``` 注意:使用聚合函数时,你需要考虑业务逻辑,确保这样聚合是合理的。 另外,建议使用显式的JOIN语法,而不是旧的逗号分隔方式。改写为: 方案1(使用显式JOIN和GROUP BY两个字段): ```sql select c.request_no, t.old_tool_gather_no from mes.tool_check c inner join mes.tool_note_requests t on c.request_no = t.request_no group by c.request_no, t.old_tool_gather_no ``` 方案2(使用聚合函数): ```sql select c.request_no, max(t.old_tool_gather_no) as old_tool_gather_no from mes.tool_check c inner join mes.tool_note_requests t on c.request_no = t.request_no group by c.request_no ``` 请根据实际业务需求选择合适的方式。 现在,根据要求,我需要在最后提出相关问题: §§相关问题§§: 1. 在SQL中,GROUP BY子句的作用是什么? 2. 在Oracle中,如果SELECT列表中的列没有包含在GROUP BY子句中,也没有使用聚合函数,会发生什么? 3. 请举例说明在GROUP BY子句中使用多个列的效果。 4. 在SQL中,除了MAX和MIN,还有哪些常用的聚合函数?</think>您的 Oracle SQL 语句存在问题,因为 **SELECT 列表中的列 `t.old_tool_gather_no` 既未包含在 GROUP BY 子句中,也未使用聚合函数包裹**。Oracle 要求 GROUP BY 查询必须满足以下规则: 1. SELECT 列表中的**非聚合列**必须全部出现在 GROUP BY 子句中 2. 未包含在 GROUP BY 中的列,必须使用聚合函数(如 `MAX()`, `MIN()`, `SUM()` 等) ### 错误原因分析 ```sql SELECT c.request_no, -- 已包含在 GROUP BY 中 ✅ t.old_tool_gather_no -- 未包含在 GROUP BY 中 ❌ 且未使用聚合函数 FROM mes.tool_check c, mes.tool_note_requests t WHERE c.request_no = t.request_no GROUP BY c.request_no; -- 只分组了一个字段 ``` 当按 `c.request_no` 分组时,每个分组可能对应多个 `t.old_tool_gather_no` 值。Oracle 无法确定该返回哪个值,因此报错 **"not a GROUP BY expression"**。 --- ### 解决方案 根据业务需求选择以下任一修改方式: #### 方案 1:将缺失列加入 GROUP BY(适用于需保留原始值) ```sql SELECT c.request_no, t.old_tool_gather_no FROM mes.tool_check c JOIN mes.tool_note_requests t ON c.request_no = t.request_no GROUP BY c.request_no, t.old_tool_gather_no; -- 添加缺失列到 GROUP BY ``` #### 方案 2:使用聚合函数(适用于取最大值/最小值等场景) ```sql SELECT c.request_no, MAX(t.old_tool_gather_no) AS old_tool_gather_no -- 使用聚合函数 FROM mes.tool_check c JOIN mes.tool_note_requests t ON c.request_no = t.request_no GROUP BY c.request_no; ``` #### 方案 3:移除冗余列(如果不需要该列) ```sql SELECT c.request_no -- 只保留 GROUP BY 中的列 FROM mes.tool_check c JOIN mes.tool_note_requests t ON c.request_no = t.request_no GROUP BY c.request_no; ``` --- ### 附加改进建议 1. **使用显式 JOIN 语法**: 用 `INNER JOIN ... ON` 替代旧式逗号连接,提高可读性。 2. **表别名优化**: 使用有意义的别名(如 `chk` 代替 `c`,`req` 代替 `t`)。 修正后的推荐写法: ```sql SELECT chk.request_no, MAX(req.old_tool_gather_no) AS old_tool_gather_no -- 聚合函数确保安全 FROM mes.tool_check chk INNER JOIN mes.tool_note_requests req ON chk.request_no = req.request_no GROUP BY chk.request_no; ``` --- ### 关键概念说明 - **GROUP BY 本质**:将数据按指定列分组,每组返回**单一行**。 - **聚合函数作用**:对组内多值进行汇总(如取最大/最小/平均值)。 - **Oracle 严格性**:比 MySQL 等数据库更严格,要求 SELECT 列表与 GROUP BY 完全匹配。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值