有没有比交易更有效的方法?

时间:2010-01-26 12:22:55

标签: php mysql transactions

insert into table1 ...;
update table2 set count=count+1;

以上内容会在table1中插入内容,如果成功,则会更新count的{​​{1}}字段。

当然这种事情可以由事务处理,但事务需要锁定表,这在高并发系统中效率不高。如果您需要更新该事务中的多个表,情况会更糟。

你的解决方案是什么?

我正在使用PHP,我以这种方式实现事务:

table2

所以看起来mysql_query('begin'); mysql_query($statement1); mysql_query($statement2); ... mysql_query('commit'); 中引用的所有表都会被锁定?

6 个答案:

答案 0 :(得分:3)

一个事务(在MySQL假设为InnoDB的上下文中)不需要锁定整个表。

INSERT将锁定单个行而没有间隙锁定。

如果您在UPDATE子句中的索引字段上提供相等或IN条件,则WHERE也不会锁定任何间隙。

这意味着,使用正确编制索引的表格,INSERTs不会互相阻止,而UPDATEs只会在相同的行中相互阻止。

UPDATE当然会锁定它影响的单个行,但由于它是事务中的最后一个操作,因此在提交操作后会立即解除锁定。

事实上,锁定本身是必需的,因此两个并发更新将按顺序递增计数。

答案 1 :(得分:2)

使用InnoDB存储引擎。它是行级锁定而不是MyISAM,它是表级锁定。

答案 2 :(得分:2)

交易不一定会请求整个表的锁定。

此外,InnoDB使用不同的锁定策略支持各种转换隔离级别。您可以查看:

答案 3 :(得分:1)

这些看起来更像是一个“触发器”工作给我。 onInsert做点什么。

答案 4 :(得分:1)

事务很好地确保“全有或全无”行为 - 即使系统中存在高负载或高并发性,您也不应该停止使用事务,至少如果您需要数据保持连贯性!

(并且交易不一定会锁定整个表格)

答案 5 :(得分:0)

如果速度是绝对的本质,我可能会试图将更新计数缓存在内存中(使用线程安全代码)并且只是定期将其写回数据库。当我这样做时,我肯定会使用交易。这样做的缺点是你需要愿意将计数视为近似值。如果您需要它完全正确的操作,那么它需要在事务中再次重新计算。

正如其他人所指出的那样,使用支持行级锁定的数据库并简单地使用显式(或隐式通过触发器)事务可能更容易。它肯定更准确,更安全。