2012-04-29 34 views
0

我想緩存的聚集,但由於併發可能會遇到一個參照完整性違規..如何管理鎖來防止重複插入

下面是我在做什麼(樣的歸結了一下) :

select low, high 
into l_low, l_high 
from nasd_stats 
where symbol_id = l_symbol_id; 

if(l_low is NULL) then 
     select max(last), 
       min(last) 
     into l_high, l_low 
     from nasd 
     where symbol_id = l_symbol_id; 

     insert into nasd_stats values (l_symbol_id, l_low, l_high); 
end if; 

所以,兩個用戶可以運行具有此代碼的存儲過程,等檢測,同時,也l_low爲空,然後都嘗試在分鐘後同時插入nasd_stats/max聚合(其中一個失敗,因爲在基於symbol_id的nasd_stats上有唯一鍵)。

任何想法如何防止發生?

我猜我能做到這一點:

Start Transaction; 
delete from nasd_stats where symbol_id = l_symbol_id; 
insert into nasd_stats values (l_symbol_id, l_low, l_high; 
Commit; 

邏輯存在,刪除將鎖定該行(即使它不存在),然後在插入會做我想做的事。

TIA。

+0

['SELECT ... FOR UPDATE'](http://dev.mysql.com/doc/refman/5.5/ en/innodb-locking-reads.html) – eggyal 2012-04-29 10:10:43

+0

涉及兩個表格。我不能選擇一個,並鎖定不參與選擇的第二個......我可以嗎? – 2012-04-29 10:30:05

+0

否,但是'SELECT ... FOR UPDATE'會鎖定第一個表,以防止併發查詢獲得'low'和'high',直到釋放鎖(提交事務後)。 – eggyal 2012-04-29 10:32:13

回答

1

如果關鍵是symbol_id領域定義,那麼在下面的方式執行查詢

insert into nasd_stats Select distinct l_symbol_id, l_low, l_high from nasd_stats where not exists (Select 1 from nasd_stats where symbol_id = l_symbol_id) ; 
+0

thx有趣的建議 - 梳理插入&不存在於一個語句。如果我理解正確,這將保證只有一行被插入唯一鍵symbol_id?第一個人看到'不存在'並插入。併發的人他插入不通過。那很好,通常的情況是一行存在,只是在啓動時它不存在。 TIA。 – 2012-04-29 11:31:16

+0

唐,你理解正確。 – 2012-04-29 12:44:27

0

你能不能爲您在您的插入符號ID,它存在那麼一個人已經有了它,所以你不需要做另一個插入?

所以,你的代碼是相同的,但插入語句將

insert into nasd_stats values (l_symbol_id, l_low, l_high) where symbol_id = l_symbol_id AND l_low is NULL ;