mysql – 如何以线程安全的方式查询和增加值(计数器)? (避免竞争条件)

在每个行都有一个计数器(只是一个整数值)的表中,我需要获取当前值并同时增加它.

实际上,我想这样做:

SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123

但是,作为两个查询执行此操作显然不是线程安全的:多个进程执行相同的操作(在同一行上)可能获得相同的计数器值.我需要它们都是唯一的,因此每个过程都会获得实际的当前值并将其增加一个.

我可以想到一个构造,我每行都实现一个手动锁定,但我想知道是否有更简单的方法可以做到这一点?

解决方法:

更新语句完全正常,没有之前的选择!由于单个语句的定义是安全的,即使同时执行的两个UPDATE查询也只会导致行增加两次.

如果您确实想要为PHP脚本选择值,请使用它执行某些操作,稍后要更新此确切的计数器值,您可以执行以下操作:

BEGIN;
SELECT `counter` FROM `table` WHERE `id` = 123 FOR UPDATE;
UPDATE `table` SET `counter` = `counter`+1 WHERE `id` = 123;
COMMIT;

这将启动一个新事务,然后选择要更新的行并将其专门锁定.然后,您可以安全地更新这些内容,而无需担心其他客户端更改其内容甚至访问锁定的行.最后,您需要提交更改.

您还应该阅读有关isolation levels的内容.您可能不希望像READ UNCOMMITTED这样的值作为隔离级别.对于这个用例,其他一切都应该没问题.

上一篇:MySQL:事务会锁定行吗?


下一篇:mysql – 如何根据十六进制转储查找谁持有锁?