我正在使用mariadb。有一个resource
表,其中包含列id
,一个used
标志和其他资源描述符。每一行代表一个资源分配单位。我在分配行时遇到麻烦。
在每笔交易中,我要:
选择并锁定非used
的行。
将used
设置为true
。
根据所选的行来操作数据库。
然后提交。
要求:
可以有许多并发事务。
它可以选择不是used
的任何一行。
它不应该阻止。
如果第3步失败,则事务将回滚并重新启动。最好选择其他行。
首先,我尝试了SELECT * FROM resource WHERE used=0 LIMIT 1 FOR UPDATE
,但在并发情况下,第二个事务将阻塞,直到第一个事务结束。
START TRANSACTION
SELECT * FROM resource WHERE used=0 LIMIT 1 FOR UPDATE <-- second tx waits here until first commits
...
COMMIT
然后,我尝试通过
ORDER BY rand()
添加随机性。但这似乎将首先对整个表进行排序,因此仍然会阻塞。START TRANSACTION
SELECT * FROM resource WHERE used=0 ORDER BY rand() LIMIT 1 FOR UPDATE <-- still blocks
...
COMMIT
有什么提示吗?
最佳答案
我假设您的处理将花费很短的时间,或者您有大量的并发事务-否则,接受阻塞可能会更容易。
过去,我通过具有“已使用”的更详细的状态来解决此问题。
用伪代码:
begin transaction
select the row to process, set status to "in progress", and mark with unique process identifier
end transaction
begin transaction
select the row with "in progress" and my unique process identifier
complete other processing logic
set row status to "used"
if error:
rollback transaction
set flag to "error"
else
commit transaction
这仍然会阻塞该表,但会持续一秒钟。
我们有一个单独的工作,寻找“被遗弃的”交易(带有“错误”标志的记录,并向管理控制台报告这些记录)。
关于mysql - 使用SQL分配资源(行),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45550613/