Php 在cron作业中迭代活动使用的数据库表,而不丢失任何行

Php 在cron作业中迭代活动使用的数据库表,而不丢失任何行,php,algorithm,orm,cron,iteration,Php,Algorithm,Orm,Cron,Iteration,在执行长操作的多个过程时,如何正确地迭代数据库查询的所有行而不丢失任何行?在我的例子中,我有字母数字id,所以id列不可靠 主要问题是,查询结果可能会在每个cron任务执行之间发生变化 第一个想法可能是存储偏移量/“处理的行数”。但是,如果已经处理的行中有一行被删除,其他行将移动,第一行将被跳过 如果我存储最后一个处理的行的id并跳到它后面的那一行,我有一个更糟糕的问题:如果删除了那一行,下一个cron作业将跳过剩下的每一行 有没有其他像这样迭代表的“标准”方法 我在php中使用第三方orm引擎

在执行长操作的多个过程时,如何正确地迭代数据库查询的所有行而不丢失任何行?在我的例子中,我有字母数字id,所以id列不可靠

主要问题是,查询结果可能会在每个cron任务执行之间发生变化

第一个想法可能是存储偏移量/“处理的行数”。但是,如果已经处理的行中有一行被删除,其他行将移动,第一行将被跳过

如果我存储最后一个处理的行的id并跳到它后面的那一行,我有一个更糟糕的问题:如果删除了那一行,下一个cron作业将跳过剩下的每一行

有没有其他像这样迭代表的“标准”方法


我在php中使用第三方orm引擎,使用sql作为数据存储,但我认为这是一个更一般的问题,因此任何人都可以更适当地重新标记它。

大多数DBMS都有可靠的标准排序。因此,最简单的解决方案是不使用任何排序并使用限制和偏移定义。例如,对于MySQL,您可以这样做:

SELECT *
FROM mytable
LIMIT 10,10
;
这应该是可靠的

如果您想考虑删除的行,我将使用某种队列。例如:

CREATE TABLE item(
    id INT PRIMARY KEY
);

CREATE TABLE job (
    id INT PRIMARY KEY
);

CREATE TABLE job_queue(
    id INT PRIMARY KEY,
    job_id INT,
    item INT,
    FOREIGN KEY job_id REFERENCES job(id),
    FOREIGN KEY item REFERENCES item(id)
);
然后,您可以通过运行以下命令将所有项目添加到队列:

INSERT INTO job_queue (job_id, item_id)
SELECT 1, id
FROM item;
现在,您可以通过运行查询可靠地获取项目:

SELECT *
FROM job_queue
WHERE job_id = 1
LIMIT 10;

DELETE FROM job_queue WHERE id IN (
    SELECT id
    FROM job_queue
    WHERE job_id = 1
)

但有许多可能的有效解决方案。最终答案在很大程度上取决于您的需求。

如果任意两个cron同时命中,您可以使用DB事务来解决并发问题。要知道下一行从哪一行开始,可以在DB say
processed
中有一个额外的列,它存储一些整数,比如1。因此,下一次cron命中将获取
processed
列中没有1的行

我想,我不确定是否在没有订单的情况下使用LIMIT,这要视情况而定。某些DBMS有一个内部行id,用于缺少顺序的情况。据我所知,以下DBMS是关于这方面的:MySQL、PostgreSQL、MSSQL如果您按ID asc(例如)排序选择并存储最后处理的ID。下次只需使用WHERE ID>stored,最好将其完全作为查询或存储过程编写,这样就可以使用SQL引擎保证不会遗漏任何行。如果做不到这一点,您可能需要添加一个timestamp列来记录最后一次“处理”行的时间。或者您可以使用Sammitch所说的timestamp列。