php - 从两个或多个脚本访问/更新一个表的最佳方法?

标签 php mysql

背景

我有一个表,其中包含两个或多个 PHP 脚本将同时访问的数据。数据看起来像这样:

+--------+-------------------+-----------+-----------+
| ID     | Start             |  End      |  Status   |
+--------+-------------------+-----------+-----------+
| 1      | 1000              | 1500      |  0        |
| 2      | 1000              | 1500      |  0        |
| 3      | 1000              | 1500      |  0        |
| 4      | 1000              | 1500      |  0        |
+--------+-------------------+-----------+-----------+

PHP 脚本在启动时执行以下查询:

SELECT * FROM `table` WHERE `Status` = 0 LIMIT 1

然后 PHP 脚本执行从 start 值到 end 值(1000 到 1500)的循环。完成后,它将该行的 Status 更新为 '1'。它会自动重定向到自身并重新启动整个过程。

我面临的挑战是:

  1. 如果我希望 2 个或更多相同的 PHP 脚本同时运行以访问相同的数据库,我如何确保它们访问相同的记录?

  2. 更大的挑战是,如果我想在同一 PHP 脚本的多个实例上拆分从 startend 的循环,即每 100 values 是脚本的一个实例,在达到 1100 后,将 MySQL Start 更新为 1100 并重定向到从 开始的同一脚本code>11011200 等等,直到达到 End 号码。在达到 End 编号后,该记录的 Status 将设置为 1 并且它将移动到下一条记录。实际情况下,从头到尾大约一百万次,循环中执行了一些内存密集型函数,所以我需要将其分块。

关于行级锁定的所有知识,都是我在最近几分钟学到的;而且这些似乎都无法回答来自一个脚本的多实例锁定。

我应该考虑 session ID/cookie 吗?你有什么建议?

最佳答案

我建议:

  1. 使用支持行级锁定的InnoDB:

    ALTER TABLE `table` ENGINE=InnoDB;
    
  2. 使用 Status 的值来指示“进行中”;更明确一点,让我们使用 MySQL 的 ENUM 类型:

    ALTER TABLE `table`
      ADD status_new ENUM('queued','in progress','complete') AFTER status;
    
    UPDATE `table` SET status_new = CASE status
      WHEN 0 THEN 'queued'
      WHEN 1 THEN 'complete'
    END;
    
    ALTER TABLE `table` DROP status;
    
  3. 在客户端中使用事务:

    $dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE);   // pdo
    $mysqli->autocommit(FALSE);                        // mysqli (OOP)
    mysqli_autocommit($link, FALSE);                   // mysqli (procedural)
    mysql_query('START TRANSACTION');                  // ext/mysql *
    
  4. 使用 locking read获取要处理的行:

    SELECT * FROM `table` WHERE status_new = 'queued' LIMIT 1 FOR UPDATE;
    
  5. 将获取行的状态设置为'in progress':

    UPDATE `table` SET status_new = 'in progress' WHERE ID = ?
    
  6. 提交交易:

    $dbh->commit();                                    // pdo
    $mysqli->commit();                                 // mysqli (OOP)
    mysqli_commit($link);                              // mysqli (procedural)
    mysql_query('COMMIT');                             // ext/mysql *
    
  7. 处理完成后,再次UPDATE记录以将其标记为这样。

请注意,您正确检测并处理了每个阶段出现的任何错误。

* 请注意,自 2011 年 6 月以来,不推荐在新代码中使用 ext/mysql,现在已在 PHP v5.5 中弃用。

关于php - 从两个或多个脚本访问/更新一个表的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16370893/

相关文章:

php - phpinfo的error_reporting 22527中的22527是什么

mysql - 其他事件之后发生的特定项目的特定事件列表

php - 搜索 LONGTEXT 字段并显示结果

php - 使用 PHPstorm 使 php 代码在浏览器中执行

MySQL 联合查询未返回预期结果,

mysql - 无法从本地计算机连接到 AWS RDS 中创建的实例

PHP GET MySQL order by 如果不为空 echo else echo 如何

php - 更新一个mysql数据库

php - 克莱因路线不返回任何内容

php - 我怎样才能在第一次出现时停止? - 拉拉维尔