Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从两个或多个脚本访问/更新一个表的最佳方法?_Php_Mysql - Fatal编程技术网

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

Php 从两个或多个脚本访问/更新一个表的最佳方法?,php,mysql,Php,Mysql,背景 我有一个包含两个或多个PHP脚本将同时访问的数据的表。数据如下所示: +--------+-------------------+-----------+-----------+ | ID | Start | End | Status | +--------+-------------------+-----------+-----------+ | 1 | 1000 | 1500 | 0

背景

我有一个包含两个或多个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脚本执行从
开始
值到
结束
值(1000到1500)的循环。完成后,它将该行的
状态更新为
'1'
。它会自动重定向到自身并重新启动整个过程

我面临的挑战是

  • 如果我希望两个或多个相同的PHP脚本同时运行以访问相同的数据库,那么如何确保它们不是访问相同的记录

  • 更大的挑战是,如果我想在同一个PHP脚本的多个实例上拆分从
    start
    end
    的循环,即每100个值是脚本的一个实例,并且在达到
    1100
    之后,将MySQL
    Start
    更新为
    1100
    ,并重定向到从
    1101
    开始的同一脚本到
    1200
    ,依此类推,直到达到
    End
    编号。达到
    结束
    编号后,该记录的
    状态
    将设置为
    1
    ,并移动到下一条记录。在实际情况中,它从开始到结束大约有一百万个计数,一些内存密集型函数在循环中执行,所以我需要将其分块

  • 关于行级锁定的所有知识,我都是在最后几分钟学到的;所有这些似乎都无法解决来自一个脚本的多实例锁定问题

    我应该考虑会话ID/Cookie吗?你推荐什么?

    我建议:

  • 使用支持行级锁定的InnoDB
  • ALTER TABLE`TABLE`ENGINE=InnoDB;
    
  • 使用
    Status
    值指示“正在进行”;为了更明确一点,让我们使用MySQL的
    ENUM
    类型:

    altertable`TABLE`
    在状态后添加状态\新枚举('queued'、'inprogress'、'complete');
    更新`table`SET status\u new=案例状态
    当0然后“排队”时
    当1“完成”时
    结束;
    改变TABLE`TABLE`的删除状态;
    
  • 在客户端内使用事务:

    $dbh->setAttribute(PDO::ATTR_AUTOCOMMIT,FALSE);//pdo
    $mysqli->autocommit(FALSE);//mysqli(OOP)
    mysqli_自动提交($link,FALSE);//mysqli(程序性)
    mysql_查询(“启动事务”);//ext/mysql*
    
  • 使用获取要处理的行:

    从'table'中选择*,其中status_new='queued'LIMIT 1用于更新;
    
  • 将提取行的
    状态设置为
    “进行中”

    UPDATE`table`SET status\u new='in progress',其中ID=?
    
  • 提交事务:

    $dbh->commit();//pdo
    $mysqli->commit();//mysqli(OOP)
    mysqli_提交($link);//mysqli(程序性)
    mysql_查询('COMMIT');//ext/mysql*
    
  • 处理完成后,
    再次更新
    记录以将其标记为该记录

  • 请注意,您可以正确地检测和处理每个阶段出现的任何错误

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

    我建议:

  • 使用支持行级锁定的InnoDB

    ALTER TABLE`TABLE`ENGINE=InnoDB;
    
  • 使用
    Status
    值指示“正在进行”;为了更明确一点,让我们使用MySQL的
    ENUM
    类型:

    altertable`TABLE`
    在状态后添加状态\新枚举('queued'、'inprogress'、'complete');
    更新`table`SET status\u new=案例状态
    当0然后“排队”时
    当1“完成”时
    结束;
    改变TABLE`TABLE`的删除状态;
    
  • 在客户端内使用事务:

    $dbh->setAttribute(PDO::ATTR_AUTOCOMMIT,FALSE);//pdo
    $mysqli->autocommit(FALSE);//mysqli(OOP)
    mysqli_自动提交($link,FALSE);//mysqli(程序性)
    mysql_查询(“启动事务”);//ext/mysql*
    
  • 使用获取要处理的行:

    从'table'中选择*,其中status_new='queued'LIMIT 1用于更新;
    
  • 将提取行的
    状态设置为
    “进行中”

    UPDATE`table`SET status\u new='in progress',其中ID=?
    
  • 提交事务:

    $dbh->commit();//pdo
    $mysqli->commit();//mysqli(OOP)
    mysqli_提交($link);//mysqli(程序性)
    mysql_查询('COMMIT');//ext/mysql*
    
  • 处理完成后,
    再次更新
    记录以将其标记为该记录

  • 请注意,您可以正确地检测和处理每个阶段出现的任何错误


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

    感谢您提供详细的答案。非常实用!这解决了第一个难题,我们可以锁定一行并将其标记为正在进行。但是对于第二个挑战,当脚本再次加载以处理记录中的下一个块时,我是否传递一个带有当前ID的GET查询字符串?或者我可以把“锁”带到下一个实例吗?@Reddox:这取决于你的安全要求。只要错误的
    GET
    字符串(无论是恶意的还是acc)没有风险(或没有伤害),您的建议就可以了