【发布时间】:2014-06-11 20:10:49
【问题描述】:
我正在编写一个 (Java) 函数,它将在多个进程中运行,它从 Derby SQL 数据库中选择一个随机用户名。我不想一次使用多个进程使用相同的用户名,所以我想添加一个“标志”列来充当锁。我读到the documentation 的事务说每个语句都是原子的,但我对我的逻辑/知识并不是 100% 有信心。
我的策略是首先选择一个随机用户名(假设我有一个表usernames,列有username 和flag):
SELECT username FROM usernames WHERE flag='0' ORDER BY RANDOM() FETCH FIRST 1 ROW ONLY;
然后将检索到的用户名传递给此(通过准备好的语句):
UPDATE usernames SET flag='1' WHERE username=? AND flag='0';
并保存返回值(更新的行数)。如果更新了 1 行,则继续使用选定的用户名。如果没有更新行,请重新开始并重试。
这是一种可靠的锁定机制来确保没有两个进程最终使用相同的用户名吗?例如。如果两个进程从SELECT 语句返回相同的用户名,是否保证只有一个进程会从UPDATE 获得结果为 1?还是我误解了声明是原子的含义?
【问题讨论】:
-
你不应该需要设置一个标志,听起来你想要做的是锁定记录,数据库应该为你处理这个。我不熟悉德比,但从快速谷歌产生https://db.apache.org/derby/docs/10.6/ref/rrefsqlj31783.html
-
@TI 我确实需要设置标志,因为一旦进程获得用户名,它可能会使用它 20 多秒,我仍然不希望 5 秒后出现另一个 proc 并使用它。
-
所有其他进程如何知道检查标志。听起来像是实现和执行这种逻辑的皮塔饼。我认为您可能会混淆原子性和并发性。锁处理并发。事务处理原子性(工作单元)。
-
@TI 所有进程都运行相同的功能,所以很容易实现。我想确保我不会遇到这样的情况:procA 找到与 where 匹配的行,procB 找到与 where 匹配的同一行,procA 进行更新,然后 procB 进行更新,并且都不知道另一个是在那里。
标签: sql concurrency sql-update derby atomic