当有人在2023/03/29到达篮子时,我已经有了一个问题,这是一个不同的PHP错误,导致服务器崩溃。我不得不手动重启PHP服务。内存不足:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/mywebsite/prod/basket/basket_global.inc.php on line 956
所以我给PHP增加了一些内存,从昨天开始我就没有服务器崩溃(Nginx / PHP 8.1 / MySQL)!
memory_limit = 256M
昨天,我的服务器又崩溃了,我不得不手动重启php服务:
systemctl restart php8.1-fpm.service
又一次,就在有人走向篮筐之后:
access.log:
185.230.yyyy.xxx - - [27/May/2023:02:15:09 +0000] "GET /us/basket HTTP/1.1" 200 10466 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16"
error.log
2023/05/27 02:15:09 [error] 3221563#3221563: *18311176 upstream timed out (110: Unknown error) while reading response header from upstream, client: 185.230.yyyy.xxxx, server: mywebsite.com, request: "GET /us/basket/ HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock", host: "mywebsite.com"
然后在日志文件中只显示upstream timed out (110: Unknown error)
错误!
它是随机发生的,不经常发生,所以我认为这是因为这个函数从篮子部分用一个无限的while循环来生成唯一的工作代码:
function get_newMerchantReference() {
global $config, $dataBase;
while(1) {
$merchantReference = mt_rand(100, 999).'-'.mt_rand(100, 999).'-'.mt_rand(100, 999);
$sql = $dataBase->prepare('SELECT count(*) AS num
FROM oo__basket_infos_hext
WHERE merchant_reference LIKE :reference');
$sql->execute(array('reference' => $merchantReference));
$countUniqueId = $sql->fetch();
$sql->closeCursor();
$sql = $dataBase->prepare('SELECT count(*) AS num
FROM oo__order_infos_hext
WHERE merchant_reference LIKE :reference');
$sql->execute(array('reference' => $merchantReference));
$countUniqueId2 = $sql->fetch();
$sql->closeCursor();
if($countUniqueId['num'] == 0 && $countUniqueId2['num'] == 0) { break; }
}
return $merchantReference;
}
这个while(1)
循环会以随机的方式出错并导致PHP服务崩溃吗?
如何修改它来生成像213-126-323这样的随机数,这些随机数还没有被使用过,并且存储在oo__basket_infos_hext
和oo__order_infos_hext
中?
1条答案
按热度按时间kdfy810k1#
如果您正在为引用生成一个随机数,那么我建议使用不太可能发生冲突的东西,比如UUID v4。碰撞的可能性非常低,你不需要一个循环来检查是否存在,你可以安全地假设没有重复。(不过,仍然要对列设置唯一约束。)
也就是说,如果您无法更改引用的格式,则可以转换为增量格式。从0开始,在数据库中使用自动递增/串行字段,并且每个记录递增1。然后用前导零和破折号格式化该值,因此0变为000- 000-000,依此类推。
如果你不能做到这一点,你需要使用这种格式,并让它是随机的,那么你需要接受它会随着时间的推移变得更慢(取决于音量),你对此无能为力。但仍有一些地方可以改进:
1.从
mt_rand()
切换到random_int()
,它提供加密安全和统一选择的输出。1.如果第一个查询返回了一行,就不需要执行第二个查询,您可以直接跳到下一个迭代,因为您已经知道您遇到了失败。
1.查询时未检查任何错误。
prepare()
和fetch()
可能返回false。1.确保两个
merchant_reference
列在数据库中具有唯一约束。这将防止意外重复。1.确保两个
merchant_reference
列都在数据库中建立了索引。这将使查找查询更快。1.对迭代次数设置硬上限: