2011-02-11 100 views
2

我有一個表格「命令可以做」與狀態(「麥克羅公司一直供應」,「加工」,「完成」)行鎖的更新狀態

我有幾個實例(亞馬遜EC2)與守護問爲「要做的命令」。

守護進程請求狀態爲「toprocess」的行,然後進行處理,並在每個循環結束時將狀態更改爲「完成」。

問題是,在開始該循環之前,我需要將所有行'toprocess'更改爲狀態'processing',所以其他實例不會採用相同的行,從而避免衝突。

我讀過有關InnoDB的行鎖,但我不明白他們很好...

SELECT *從那裏狀態=「麥克羅公司一直供應」 然後我需要這些結果的ID的命令,並將狀態更新爲'處理',鎖定這些行直到它們更新。

我該怎麼辦?

謝謝

回答

0

據我知道你不能使用MySQL來鎖定行(使用內置的方法)。你有兩個選擇,但:

  1. 如果您的表不應該由任何其他進程讀取,直到鎖被釋放,那麼你可以使用表級鎖as described here

  2. 你可以實現你自己的基本行鎖定通過更新你正在處理的每一行中的一個值,然後讓所有其他的守護進程檢查這個屬性是否被設置(一個BIT數據類型就足夠了)。

InnoDB鎖定在行級讀取和更新,但是如果你想鎖定任意時間段的行,那麼你可能必須去第二個選項。

+0

嗨,...表鎖定太多「沉重」(思考在應用程序的其餘部分)...你告訴的第二個選擇似乎解決方案...我怎麼能做到這一點? – FlamingMoe 2011-02-11 17:22:18

1

的可能(但不是很優雅)的解決方案可能是第一個更新的記錄,然後讀取其數據:

每個守護進程都會有一個唯一的ID,並且該表將有一個名爲「所有者」新列爲那個ID。 然後,deamon將運行類似於「更新表SET狀態='處理',所有者='theDeamonId'其中status ='toprocess'... LIMIT 1」

當更新運行行被鎖定,其他deamon可以閱讀它。 更新後,此行由特定的deamon擁有,然後它可以運行SELECT從該行獲取所有必要的數據(WHERE status ='processing'AND owner ='theDeamonId')。

最後,最後一次UPDATE會將該行設置爲'已處理',並且可能(或可能不)刪除所有者字段。將它保留在那裏也會使關於deamons工作的一些統計數據成爲可能。

3

你會使用一個事務,並讀取用於更新的數據,這將阻止其他選擇,其中包括那個被選中

begin transaction; 
select * from commands where status = 'toprocess' for update; 
for each row in the result: 
    add the data to an array/list for processing later. 
    update commands set status='processing' where id = row.id; 

commit; 

process all the data 

瞭解一點關於FOR UPDATE的行FOR UPDATE,和InnoDB isolation levels