2011-08-11 34 views
5

因此,我正在編寫一個簡單的網站爬蟲,用於維護內部網站。它會通過每個鏈接,添加新的鏈接,因爲它發現它們,注意到標題和H1標籤等。MySQL在更新的選擇查詢中鎖定行

它偶爾會重複標題和H1標籤,當源中只有一個時,我手動檢查它。

出現這種情況的原因是因爲抓取腳本通過cron運行,它似乎是重疊的,所以在處理同一個頁面的兩倍。

該腳本將基本搶已未抓取頁面,那麼如果HTTP響應是200,將其標記爲抓取和處理它所需要。

因此,SELECT和UPDATE之間的某處,腳本的另一個線程上選擇了同一行運行。

有沒有辦法要麼SELECT和UPDATE在相同的查詢,或鎖定在SELECT返回的行,因此它不能再在另一個線程另一個查詢,直到我完成了它回來了?

有在當時一看 - http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html和一般的SELECT FOR UPDATE的東西,但我仍然不確定。

編輯

我使用這樣的事情

START TRANSACTION; 
SELECT .. FOR UPDATE; 
UPDATE .... ; 
COMMIT; 

但它不喜歡它。我在這張桌子上使用InnoDB。我認爲這可能不是前進的方向,因爲它直接提交行的處理直到提交後,當我希望它實際上不能再次選擇行時。

我已經通過執行SELECT覆蓋了這一點,然後在處理它之前執行UPDATE以標記字段爲已爬網字段,但事實是這不是無縫的,這似乎是導致問題的原因。我需要一種方法來無縫地選擇和更新字段,或選擇並停止它被再次選擇,直到我這樣說。

回答

3

你自己回答了這個問題:)。如果我正確理解你的問題,SELECT FOR UPDATE正是你所需要的。請記住關閉自動提交,在選擇並在更新後提交事務之前啓動事務。

更新:

我認爲這會做你想要什麼:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
BEGIN TRANSACTION; 
SELECT .. FOR UPDATE; 
UPDATE .... ; 
COMMIT TRANSACTION; 
+0

任何一個例子的機會呢?我已向OP添加了更多信息,但我沒有任何運氣 – Horse

+0

ISOLATION LEVEL SERIALIZABLE有什麼作用?我讀過這個(http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_serializable),但沒有多大意義。謝謝! –

3

當你鎖定該行(通過選擇用於更新),其他事務將等待鎖被釋放,而不是跳過這一行並選擇下一行。更好的策略是在表格中設置一個標誌柱(無,處理完成),也許有一個時間戳。 cron抓取行,將標記設置爲處理並開始處理頁面。當腳本的另一個實例正在運行時,它將選擇不處於「處理」狀態的行。 cron什麼時候共完成,它再次更新記錄爲「完成」

+1

這就是我在莫,但在中間的選擇和更新改變國旗處理,其有時被重新選擇在一個重疊的線程 – Horse

+0

cron作業是每分鐘運行,但其運行PHP的sh腳本腳本30秒,間隔2秒 – Horse

+0

使用選擇更新 - 想法是保持鎖定的最短時間 –