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');
中引用的所有表都会被锁定?
答案 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)
如果速度是绝对的本质,我可能会试图将更新计数缓存在内存中(使用线程安全代码)并且只是定期将其写回数据库。当我这样做时,我肯定会使用交易。这样做的缺点是你需要愿意将计数视为近似值。如果您需要它完全正确的操作,那么它需要在事务中再次重新计算。
正如其他人所指出的那样,使用支持行级锁定的数据库并简单地使用显式(或隐式通过触发器)事务可能更容易。它肯定更准确,更安全。