我正在使用mariadb。有一个resource
表,列id
,used
标志和其他资源描述符。每行代表一个资源分配单元。我在分配一行时遇到了麻烦。
在每笔交易中,我想:
used
的行。used
设为true
。要求:
used
的行。首先我尝试了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
任何提示?
答案 0 :(得分:1)
我认为你的处理需要花费大量的时间,或者你有大量的并发事务 - 否则,接受阻塞可能会更容易。
我过去通过更细粒度的“使用”状态解决了这个问题。
在伪代码中:
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
这仍然会阻止该表,但只需几分之一秒。
我们有一个单独的工作,寻找“废弃”的交易(带有“错误”标志的记录,并在管理控制台上报告)。