2013-01-31 40 views
0

我只是想知道mysql「SELECT FOR UPDATE」鎖是否阻塞了一個進程中的所有線程,以及如果我需要在多線程應用程序中授予此鎖,如何通過它。MySQL SELECT FOR UPDATE鎖定所有線程?

爲了簡單起見,我只給一個簡單的測試代碼中的紅寶石:

t1 = Thread.new do 
    db = Sequel.connect("mysql://abcd:[email protected]:3306/test_db") 
    db.transaction do 
    db["select * from tables where id = 1 for update"].first 
    10.times { |t| p 'babababa' } 
    end 
end 

t2 = Thread.new do 
    db = Sequel.connect("mysql://abcd:[email protected]:3306/test_db") 
    db.transaction do 
    db["select * from tables where id = 1 for update"].first 
    10.times { |t| p 'lalalala' } 
    end 
end 

t1.join 
t2.join 
p 'done' 

實際上,其結果將是:

線程1和一個後線程2掛起至少50秒的線程獲取「FOR UPDATE」LOCK(鎖定等待時間在Mysql設置中的等待時間爲50秒),然後一個線程將「超出鎖定等待超時」錯誤並退出,另一個線程成功打印出'baba'或'lala' 。

+0

您正在使用哪種存儲引擎? –

+0

innodb,帶有mysql 5.1版本 –

回答

2

這與mysql驅動程序爲每個查詢鎖定整個ruby虛擬機有關。當第二個線程遇到FOR UPDATE鎖定並凍結時,在ruby中沒有任何事情發生,直到超時,導致您看到的行爲。

安裝mysqlplus gem(我不會阻塞整個解釋器,如果安裝了Sequel的mysql適配器將自動使用),或者安裝mysql2 gem並使用mysql2適配器而不是mysql適配器。