我在C API中使用mySQL,但这不应该是相关的。 我的代码必须处理符合某些条件的表中的记录,然后更新所述记录以将它们标记为处理完毕。表中的行被我不控制的另一个进程修改/插入/删除。我在下面很害怕,更新可能标志的一些记录错误,因为该集记录匹配的可能步骤1和步骤3SQL(mySQL)更新某个select所处理的所有记录中的某些值
SELECT * FROM myTable WHERE <CONDITION>; # step 1
<iterate over the selected set of lines. This may take some time.> # step 2
UPDATE myTable SET processed=1 WHERE <CONDITION> # step 3
什么是聪明的方式,以确保之间已经改变了update更新所有的行处理,只有他们?交易似乎不符合该法案,因为它没有提供这种隔离:最近修改的记录不在最初选择的集合中,可能仍然是UPDATE语句的目标。出于同样的原因,SELECT ... FOR UPDATE似乎没有帮助,但它听起来很有前途:-)
我能看到的唯一方法是使用临时表来记忆要处理的行集,做类似的事情:
CREATE TEMPORARY TABLE workOrder (jobId INT(11));
INSERT INTO workOrder SELECT myID as jobId FROM myTable WHERE <CONDITION>;
SELECT * FROM myTable WHERE myID IN (SELECT * FROM workOrder);
<iterate over the selected set of lines. This may take some time.>
UPDATE myTable SET processed=1 WHERE myID IN (SELECT * FROM workOrder);
DROP TABLE workOrder;
但是这看起来很浪费,效率也不是很高。
有什么更聪明的吗?
非常感谢来自SQL新手。
1-锁定表格意味着阻止另一个进程在我正在处理时工作。它不会很高兴... 2-没有临时表,你怎么能表达all_the_ids_you_processed?我提前对处理后的记录感到有些不舒服,所以我可以稍后选择它们,因为它是侵入性的:需要一个新的“timeStamp”列。另外,时间戳很棘手,因为时间并不总是单调的:例如它可以倒退(例如,当夏令时间关闭时)。 然后,临时表是一个非常糟糕的主意吗? – 2010-01-21 10:53:58
而不是时间戳,使用多值状态字段。让未处理的行具有状态0(说);你做一个更新,将状态设置为1(意味着正在处理中),然后执行处理,然后执行另一个更新以将状态设置为2(表示进入处理)。 – 2010-01-21 21:29:38
是的,我想这可以解决问题,因为我描述了它。但我最终决定记住客户端应用程序中已处理记录的ID。 – 2010-01-23 22:22:58