Php cron上的MySQL查询重叠,忽略“锁定”行

Php cron上的MySQL查询重叠,忽略“锁定”行,php,mysql,Php,Mysql,我试图将表中的一行锁定为正在使用中,这样当cron每分钟运行一次时,我就不会对数据进行两次处理。由于脚本运行所需的时间较长,cron将导致脚本的多个实例同时运行,通常一次运行5或6个左右。由于某种原因,我的在用方法并不总是有效 我不想锁定这些表,因为我需要它们可用于同时处理,这就是为什么我使用带有“inuse”字段的伪锁定单个行的原因。我不知道有什么更好的方法可以做到这一点 以下是我的困境的一个例子: <? //get the first row from table_1 tha

我试图将表中的一行锁定为正在使用中,这样当cron每分钟运行一次时,我就不会对数据进行两次处理。由于脚本运行所需的时间较长,cron将导致脚本的多个实例同时运行,通常一次运行5或6个左右。由于某种原因,我的在用方法并不总是有效

我不想锁定这些表,因为我需要它们可用于同时处理,这就是为什么我使用带有“inuse”字段的伪锁定单个行的原因。我不知道有什么更好的方法可以做到这一点

以下是我的困境的一个例子:

 <?
    //get the first row from table_1 that is not in use
    $result = mysqli_query($connect,"SELECT * FROM `table_1` WHERE inuse='no'");
    $rows = mysqli_fetch_array($result, MYSQLI_ASSOC);
    $data1 = $rows[field1];

    //"lock" our row by setting inuse='yes'
    mysqli_query($connect,"UPDATE `table_1` SET inuse='yes' WHERE field1 = '$data1'");

    //insert new row into table_2 with our data if it doesn't already exist
    $result2 = mysqli_query($connect,"SELECT * FROM `table_2` WHERE field='$data2'");
    $numrows = mysqli_num_rows($result2);
    if($numrows >= 1) { 
      //do nothing
    } else {
      //run some unrelated script to get data
      $data2 = unrelatedFunction();

      //insert our data into table_2
      mysqli_query($connect,"INSERT INTO `table_2` (field) value ('$data2')");
    }

    //"unlock" our row in table_1
    mysqli_query($connect,"UPDATE `table_1` SET inuse='no' WHERE field1 = '$data1'");
 ?>

您将在这里看到,如果一行已经存在$data2,那么$data2将不会被收集和插入,但是该部分用于错误检查,并且不会回答我的问题,因为错误仍然发生。我试图理解为什么如果我没有在那里进行错误检查,我的“inuse”方法有时会被忽略,并且我会在表2中得到重复的行,其中包含$data2。

在您的第一次选择和第一次更新之间有很多时间,其他进程可以执行相同的操作。您也并没有使用事务,所以不能保证任何更改顺序对其他人可见


您可以将所有内容移动到具有所需隔离级别的事务中,并使用SELECT。。。。更新。或者你可以试着用另一种方式复制。例如,更新要在\u use=当前\u pid中处理和设置的N行,其中in\u use为空。然后,可以读回手动标记要处理的行。完成后,将in_use重置为NULL。

重写查询:从表1中选择*并在其中使用'no'进行更新,这将在SELECT检索行时锁定记录,并防止其他会话获得相同的结果。@kordirko:注意,这将需要一个支持锁定的数据库引擎,例如,InnoDB。但无论如何,你不应该使用MyISAM@duskwuff,谢谢你的评论,你是对的,SELECT for UPDATE将只在InnoDb上工作,并且只在与read UNCOMMITED不同的隔离级别上工作。你最初从哪里获得$data2?它也是第一个查询中的字段吗?相关:+1相关以选择。。。更新内容: