2010-01-26 82 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

如果速度是绝对的本质,我也许会在内存中缓存更新计数(使用线程安全的代码)和只能定期将其写回数据库。当我这样做的时候,我肯定会使用一个交易。这样做的缺点是您需要愿意将计数视为近似值。如果你需要它对于一个操作是绝对正确的,那么它需要重新计算,在一次交易中。如其他人所指出的那样,使用支持行级锁定的数据库并简单地使用显式(或隐式通过触发器)事务可能更容易。它绝对更准确,更安全。

相关问题