Skip to main content
 首页 » 编程设计

php之防止 PHP 在运行并行实例时发送多封电子邮件

2024年11月01日3linjiqin

这更像是一个逻辑问题而不是语言问题,尽管方法可能因语言而异。在本例中,我使用的是 Actionscript 和 PHP。

我有一个 Flash 图形,它正在获取存储在 PHP 脚本提供的 mysql 数据库中的数据。这部分工作正常。每次触发时它都会循环遍历数据库条目。

该图片不在网站上,但在 5 个位置使用,设置为定期加载和运行(所有 5 个位置同时触发,或者至少在彼此 <500 毫秒内触发)。这是实时信息,所以时间很重要,目前脚本在 30ms-300ms 之间加载和解析所有 5 个位置(取决于与服务器的距离)

我最初有一个分页问题,​​5 个位置中的每一个都会拉取不同的数据库条目,因为每次脚本运行时我都会移动到下一个条目。我通过将脚本设置为仅在经过一定时间后才移动到下一个条目来解决这个问题,解决了这个问题。

但是,我还需要脚本在每次显示新条目时发送一封电子邮件,我只希望它发送一封电子邮件。我试图通过向数据库添加“已通过电子邮件发送” bool 值来解决此问题。但是,由于所有脚本同时运行,这很少起作用(有时会起作用)。大多数时候我会收到 5 封电子邮件。发送此电子邮件的及时性不必像图形从脚本中获取信息一样快,延迟 5-10 秒就可以了。

我一直在想办法解决这个问题。目前我正在考虑通过 PHP 生成一个 python 脚本,它有一个随机延迟(2 到 5 秒之间),希望能缓解这个问题。但是,我不太确定如何在脚本不等待命令完成的情况下从 php 运行 exec() 命令。或者,是否有更好的方法来实现这一点?

更新:这是我当前的逻辑(仅相关代码):

//get the top "unread" information from the database 
 
$query="SELECT * FROM database WHERE Read = '0' ORDER BY Entry ASC LIMIT 1"; 
 
 
   //DATA  
    $emailed = $row["emailed"]; 
    $Entry = $row["databaseEntryID"]; 
 
 
if($emailed == 0) 
 
{ 
 
**CODE TO SEND EMAIL** 
 
$EmailSent="UPDATE database SET emailed = '1' WHERE databaseEntryID = '$Entry'"; 
$mysqli->query($EmailSent); 
} 

谢谢!

请您参考如下方法:

您需要使用某种锁定。例如。数据库锁定

function send_email_sync($message) 
{ 
    sql_query("UPDATE email_table SET email_sent=1 WHERE email_sent=0"); 
    $result = FALSE; 
    if(number_of_affacted_rows() == 1) { 
        send_email_now($message); 
        $result = TRUE; 
    } 
    return $result; 
} 

函数 sql_querynumber_of_affected_rows 需要适应您的特定数据库。

旧答案:

使用基于文件的锁定:(仅当脚本仅在单个服务器上运行时才有效)

function send_email_sync($message) 
{ 
    $fd = fopen(__FILE__, "r"); 
    if(!$fd) { 
        die("something bad happened in ".__FILE__.":".__LINE__); 
    } 
    $result = FALSE; 
    if(flock($fd, LOCK_EX | LOCK_NB)) { 
        if(!email_has_already_been_sent()) { 
            actually_send_email($message); 
            mark_email_as_sent(); 
            $result = TRUE; //email has been sent 
        } 
        flock($fd, LOCK_UN);     
    } 
    fclose($fd); 
    return $result; 
}