【问题标题】:MySQL query on cron overlaps, ignores 'locked' rowscron 上的 MySQL 查询重叠,忽略“锁定”行
【发布时间】:2013-09-08 22:00:39
【问题描述】:

我正在尝试将表中的一行锁定为“正在使用”,这样当我的 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,但该部分用于错误检查,由于错误仍然存​​在,因此无法回答我的问题。我试图理解为什么(如果我在那里没有那个错误检查)我的“使用”方法有时会被忽略,并且我在 table_2 中得到重复的行,其中包含 $data2。

【问题讨论】:

  • 将查询:SELECT * FROM table_1 WHERE inuse='no'改写成SELECT * FROM table_1 WHERE inuse='no' FOR UPDATE,这样会在SELECT检索行时锁定记录,防止其他会话得到同样的结果。
  • @kordirko:请注意,这需要支持锁定的数据库引擎(例如 InnoDB)。但无论如何你都不应该使用 MyISAM!
  • @duskwuff,谢谢你的评论,你是对的,SELECT FOR UPDATE 只能在 InnoDb 上工作,并且只能在不同于read uncommitted的隔离级别上工作
  • 您最初从哪里获得$data2?它也是第一个查询的字段吗?

标签: php mysql


【解决方案1】:

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

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

【讨论】:

猜你喜欢
  • 2011-05-05
  • 2016-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多