我正在翻阅这本书:高性能MySql第二版。在第四章中,它说:
在表中保持计数的应用程序在更新计数器时可能会遇到并发问题。这类表在web应用程序中非常常见。为了使事情尽可能简单,假设您有一个带有单行的计数器,它只计算网站上的点击数: mysql> CREATE TABLE hit_counter ( cnt int无签名null ) ENGINE=InnoDB;网站上的每一次点击都会更新计数器: mysql> UPDATE hit_counter SET = cnt + 1;问题是这一行实际上是更新计数器的任何事务的全局“互斥”。它将序列化这些事务。通过保留多行和更新随机行,可以获得更高的并发性。下面是更改: mysql> CREATE (时隙丁INT无符号null主键,cnt int无符号null ) ENGINE=InnoDB;通过向表中添加100行预填充表。现在,查询只需选择一个随机插槽并更新它:
mysql> UPDATE hit_counter SET cnt = cnt + 1 WHERE slot = RAND() * 100;检索统计信息,只需使用聚合查询: mysql>从hit_counter选择和(Cnt);
由于有两种不同的查询,一种是增加cnt,另一种是计算cnt之和,为什么它会给两个同时执行的不同线程带来正确的结果?例如,t1触发第一个查询以增加cnt,在获取和t2之前,t2也会更新cnt,而t1的第二个查询将获取错误的结果。请澄清。
如果你没有这本书,请参考这。
发布于 2013-10-18 08:18:38
正是事务隔离确保了一致的结果。
在您的示例中,如果您担心第一个查询和第二个查询之间其他线程可能发生的更改,则应该将查询包含在一个事务中:如果禁用了autocommit,则这是隐含的,否则可以显式声明:
START TRANSACTION;
UPDATE hit_counter SET cnt = cnt + 1 WHERE slot = RAND() * 100;
SELECT SUM(cnt) FROM hit_counter;
COMMIT;但也必须指出,在许多实际用例中(比如网页上访问的计数器),取得与先前增量一致的结果并不那么重要。
有关可能的事务隔离级别的详细说明,请参阅:http://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
https://dba.stackexchange.com/questions/51736
复制相似问题