这么说吧 col
是0,并且100个客户机正试图同时将其增加1,这里是否需要锁表?
LOCK TABLE tbl;
UPDATE tbl SET col = col + 1;
UNLOCK TABLE;
或者我可以这样做吗
UPDATE tbl SET col = col + 1;
确保col变成100(例如,mariadb确保它们都不会读取相同的值两次~)
我基本上是在尝试做这个php代码的等效代码
$fp = fopen("counter.txt", "r+b");
flock($fp, LOCK_EX);
$number = (int) stream_get_contents($fp);
$number += 1;
rewind($fp);
fwrite($fp, (string) $number);
flock($fp, LOCK_UN);
fclose($fp);
但是用数据库而不是文本文件
我怀疑mariadb和mysql在这一点上有什么区别,但如果有,我想了解一下,所以将两者都标记起来(作为一个轶事,我在工作中使用mysql,在家中使用mariadb~)
2条答案
按热度按时间fzsnzjdm1#
首先,不要使用myisam,使用innodb。不要使用
LOCK TABLES
与innodb合作。在任何情况下,对于单个查询都不需要任何类型的锁。查询具有隐式锁(米桑锁着table;innodb锁定行。)
当您有多个语句需要“原子”地保存在一起时,就需要锁/事务。请注意您的示例如何执行读写操作,以及如何使用read值执行某些操作。
innodb中的等效值(伪代码):
是的,
UPDATE table SET num = num + 1
在原子上做同样的事情,但是它不允许你用num
.mariadb有一个
RETURNS
在某些情况下。有LAST_INSERT_ID()
. 但是,如果您希望有多个线程处理同一数据,那么您就应该真正考虑多语句事务的规则,这些是有限的例外。yshpjwxd2#
首先:您的查询似乎缺少
WHERE
子句,指定应更新哪一行。大概,您会为此使用一个主键列,比如id
-例如:现在,假设您有许多并发进程同时运行这个查询,那么我不建议手动锁定行。相反,让数据库为您管理并发性。它实际上会在后台为您锁定该行,并按顺序执行并发查询,在提交上一个事务时将该行移交给下一个事务。如果初始值为
0
还有一些100
并发进程,您将以100
作为最终值。