2014-01-29 85 views
1

我有兩個表:一個存儲數據,另一個存儲鎖以指示用戶何時使用該數據。我想從第一個表中選擇一些項目,以使它們符合多個條件,並且在另一個表中沒有相應的鎖定,然後將這些項目的鎖定添加到第二個表格。由於許多用戶可能會同時嘗試鎖定物品,因此有必要以原子方式完成此操作。將INSERT ... SELECT語句原子化爲

我已經寫了下面的SQL語句來嘗試這樣做,但我收到錯誤Deadlock found when trying to get lock;

INSERT INTO table2 (id, user, date) 
    SELECT id, ?, NOW() 
    FROM table1 
    LEFT JOIN table2 USING id 
    WHERE locked IS NULL AND <several conditions on table1> 
    ORDER BY date 'DESC' 
    LIMIT 15; 

有什麼辦法可以使這個原子操作沒有鎖定表嗎?目前我正在使用一個事務,如果它不成功,就重新嘗試,但是我對這是否可以避免感興趣。我在InnoDB上使用MySQL版本5.0.95。

感謝

編輯

已經給出一些這方面的進一步的思考,我意識到,雖然鎖定表1是不可接受的,我可以鎖定表2。由於我實際上無法鎖定表中的表(因爲如果選擇鎖定其中一個表,我必須鎖定所有表),我可以使用GET_LOCK創建互斥鎖,以防止多個進程同時調用此代碼。我還沒有機會測試這種方法,但感覺它可能是比事務更輕量級的解決方案。

+0

與您的問題無關,但如果鎖定是table2中的字段,則必須將其上的過濾器從where子句移至join子句。否則,你實際上有一個內部聯接。 –

+0

由於我不知道不同類型的連接,因此我肯定需要詳細瞭解連接如何工作。如果第一個表中的大部分項目都有相應的鎖,我認爲您的建議可以提高性能?由於表2通常是空的,它是否提供任何其他好處? – tgt

回答

1

不,這是交易的全部內容。他們在組織了一堆陳述,一個原子操作成功或失敗的整體。

Here你能找到樂觀pesimistic鎖,也許你能找到一些有用的解釋。你可以在InnoDB中找到一些關於鎖定機制的細節(pesimistic locking)。 Here你可以找到關於如何在mysql中實現樂觀鎖定的指導。

希望我幫了忙!