SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123
但是将其作为两个查询来执行显然不是线程安全的:多个进程对同一行进行相同操作可能会获得相同的计数器值。我需要它们都是唯一的,所以每个进程都会获得实际的当前值并将其递增一次。
我可以想到一种方法,即为每行实现一个手动锁定,但我想知道是否有更简单的方法?
SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123
但是将其作为两个查询来执行显然不是线程安全的:多个进程对同一行进行相同操作可能会获得相同的计数器值。我需要它们都是唯一的,所以每个进程都会获得实际的当前值并将其递增一次。
我可以想到一种方法,即为每行实现一个手动锁定,但我想知道是否有更简单的方法?
BEGIN;
SELECT `counter` FROM `table` WHERE `id` = 123 FOR UPDATE;
UPDATE `table` SET `counter` = `counter`+1 WHERE `id` = 123;
COMMIT;
这将开始一个新的事务,然后选择要更新的行并独占锁定它们。您可以安全地更新这些行,而不必担心其他客户端更改其内容甚至访问已锁定的行。最后,您需要提交您的更改。
您还应该阅读一些关于隔离级别的内容。您可能不希望使用像“读取未提交”这样的隔离级别。对于这种用例,其他所有隔离级别都应该是可以接受的。
UPDATE table SET counter = counter + 1被认为是足够原子性的。你还需要将其包裹在事务语句中吗? - CMCDragonkaiFOR UPDATE和事务,那么你选择的值可能与更新查询中使用的值不同。我组合的查询在选择值后立即锁定行,因此确保在更新查询中使用这个确切的计数器值。 - Ulrich Thomas Gabor