我在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