php - cron 上的 MySQL 查询重叠,忽略 'locked' 行

标签 php mysql

我试图将表中的一行锁定为“正在使用”,这样当我的 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”方法有时会被忽略,并且我在 table_2 中收到重复的行,其中包含 $data2 。

最佳答案

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

您可以将所有内容移至具有所需隔离级别的事务中,并使用SELECT .... FOR UPDATE syntax 。或者您可以尝试以不同的方式进行复制。例如,更新您要处理的 N 行并 SET in_use=your_current_pid WHERE in_use IS NULL。然后,您可以读回手动标记为要处理的行。完成后,将 in_use 重置为 NULL

关于php - cron 上的 MySQL 查询重叠,忽略 'locked' 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18689060/

相关文章:

mysql - 如何对 MySQL 中的一个或另一个案例进行求和?

mysql - 多个订单(日期和时间)在 MYSQL 中不起作用

php - 为什么在 php 中 include() 和 require() 失败时报告两个错误

php - 列表框和 mysql 值

php - 从 PHP 中的 shell_exec 调用时不显示 MySQL 表轮廓

php MySql 错误为 null

PHP MySQL 区分/分组

php - 从 PHP 执行 GIT 命令并返回错误消息

javascript - 处理对 PHP url 的 AJAX 请求以获取 JSON 数据。我无法传递数据

javascript - 更新textarea上的mysql数据点击关闭