2014-03-07 41 views
1

我將有多個客戶端將數據輸入到數據庫中,並且我必須確保事務不會混雜在一起。SELECT FOR UPDATE在MySQL中保存整個表而不是逐行

我的文檔中讀取START TRANSACTIONSELECT ... FOR UPDATE鎖定每一行,它讀取:

的SELECT ... FOR UPDATE讀最新的數據,就可以讀取每一行設置獨佔鎖定。因此,它設置了與搜索的SQL UPDATE在行上設置的鎖相同的鎖。

https://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

所以我登錄一個客戶端和類型化這些語句:

START TRANSACTION; 
SELECT * FROM productMacAddress WHERE status='free' limit 8 FOR UPDATE; 

暫停這裏第二客戶端項....

UPDATE productMacAddress SET status='testing1' WHERE status='free' LIMIT 8; 
COMMIT; 

而在另一個客戶端,我類型:

START TRANSACTION; 
SELECT * FROM productMacAddress WHERE status='free' limit 4 FOR UPDATE; 
UPDATE productMacAddress SET status='testing2' WHERE status='free' LIMIT 4; 
COMMIT; 

但我無法從表SELECT什麼,直到第一個客戶是完全做得到。這是爲什麼發生?該文件聲明它應該逐行鎖定,尤其是因爲我LIMIT 8

預先感謝您。

回答

1

InnoDB表的默認隔離級別是可重複讀取的。當此隔離級別是活動我們得到了以下行爲(引自:https://dev.mysql.com/doc/refman/5.5/en/set-transaction.html):

用於鎖定讀取(SELECT與FOR UPDATE或LOCK IN SHARE MODE), UPDATE和DELETE語句,鎖定取決於是否 語句使用具有唯一搜索條件或範圍類型搜索條件的唯一索引。對於具有唯一搜索 條件的唯一索引,InnoDB只鎖定找到的索引記錄,而不鎖定其之前的空位 。對於其他搜索條件,InnoDB將掃描的索引範圍 鎖定到 使用間隙鎖或下一個鍵(間隙加索引記錄)鎖到其他會話的塊插入到該範圍所覆蓋的間隙中。

換句話說:你可以嘗試在SELECT的WHERE條件中使用主鍵嗎?因此,例如,而不是:

START TRANSACTION; 
SELECT * FROM productMacAddress WHERE status='free' limit 8 FOR UPDATE; 

嘗試:

START TRANSACTION; 
SELECT * FROM productMacAddress WHERE id=10 FOR UPDATE; 

的情況下,id是主鍵。任何其他具有唯一索引的列也可以工作。在WHERE子句中使用非唯一列時,InnoDB將鎖定一系列行。

相關問題