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

时间:2014-05-14 15:41:38

标签: php python email exec

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

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

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

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

但是,我还需要脚本在每次显示新条目时发送电子邮件,我只希望它发送一封电子邮件。我试图通过向数据库添加“已发送电子邮件”布尔值来解决此问题。但是,由于所有脚本同时运行,这很少有效(有时会这样)。大多数时候我收到了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);
}

谢谢!

2 个答案:

答案 0 :(得分:2)

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

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;
}

答案 1 :(得分:0)

您需要使用事务锁定数据库中的行。

psuedo代码:

Start transaction
select row .. for update
update row
commit


if (mysqli_affected_rows ( $connection )) >1
    send_email();