2010-01-26 84 views
3
insert into table1 ...; 
update table2 set count=count+1; 

以上插入東西到table1,如果成功,更新table2count字段。有沒有比交易更有效的方法?

當然這種事情可以通過事務處理,但事務需要鎖定表,這在高併發系統中效率不高。如果您需要更新該事務中的多個表,則可能會更糟糕。

您的解決方案是什麼?

我使用PHP,我執行的交易是這樣的:

mysql_query('begin'); 

mysql_query($statement1); 

mysql_query($statement2); 
... 
mysql_query('commit'); 

因此,它看起來像那些$statement提到的所有表將被鎖定?

回答

1

這些看起來更像是一個「觸發器」工作給我。 onInsert做些什麼。

+0

哪個版本的MySQL具有穩定的觸發器? – user198729 2010-01-26 12:36:46

+0

> = 5.1.6 http://dev.mysql.com/doc/refman/5.1/en/create-trigger.html – Rufinus 2010-01-26 13:09:09

3

交易(在MySQL的上下文中假設爲InnoDB)不需要鎖定整個表格。

INSERT將鎖定單行無間隙鎖定。

如果您在WHERE子句的索引字段中提供了相等條件或IN條件,UPDATE也不會鎖定任何間隔。

這意味着,使用正確索引的表格,INSERTs不會彼此阻擋,而UPDATEs只會在對同一行有影響的情況下互相阻止。

UPDATE當然會鎖定它影響到的單個行,但由於它是您的事務中的最後一個操作,所以在操作提交後立即解除鎖定。

鎖定本身實際上是必需的,因此兩個併發更新將按順序遞增計數。

+0

INSERT不能用行鎖互相阻塞,但它們仍然可以與表中的索引,實際上是彼此之間的死鎖。我已經看過了。 – MarkR 2010-01-26 13:41:31

+0

'@ MarkR':你是對的,這就是爲什麼我特別提到「正確索引表」。這裏有一個關於你正在談論的問題的問題:http://stackoverflow.com/questions/1974890/mysql-stored-procedure-causing-problems – Quassnoi 2010-01-26 13:53:43

2

使用InnoDB存儲引擎。它是行級鎖定而不是MyISAM,它是表級鎖定。

+0

或者你可以切換到Oracle(大多數情況下)不執行鎖定。 :) – LBushkin 2010-01-26 12:34:55

+0

'@ LBushkin':在'Oracle'中的永久表上的任何'DML'操作都會鎖定受影響的行直到事務結束。 – Quassnoi 2010-01-26 12:49:32

+0

Oracle將鎖定相關的行 - 必須獲取正確的事務行爲。 – MarkR 2010-01-26 13:40:20

1

交易非常適合確保「全部或全部」行爲 - 即使系統中存在高負載或高併發性,您也不應停止使用事務,至少如果您需要數據保持一致!

(和交易不一定會鎖定整個表(S))

0

如果速度是絕對的本質,我也許會在內存中緩存更新計數(使用線程安全的代碼)和只能定期將其寫回數據庫。當我這樣做的時候,我肯定會使用一個交易。這樣做的缺點是您需要願意將計數視爲近似值。如果你需要它對於一個操作是絕對正確的,那麼它需要重新計算,在一次交易中。如其他人所指出的那樣,使用支持行級鎖定的數據庫並簡單地使用顯式(或隱式通過觸發器)事務可能更容易。它絕對更準確,更安全。

相關問題