使用SQL分配资源(行)

时间:2017-08-07 15:29:14

标签: mysql sql mariadb

我正在使用mariadb。有一个resource表,列idused标志和其他资源描述符。每行代表一个资源分配单元。我在分配一行时遇到了麻烦。

在每笔交易中,我想:

  1. 选择并锁定非used的行。
  2. used设为true
  3. 根据所选行操作数据库。
  4. 然后提交。
  5. 要求:

    • 可以有很多并发事务。
    • 它可以选择任何不是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
    

    任何提示?

1 个答案:

答案 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

这仍然会阻止该表,但只需几分之一秒。

我们有一个单独的工作,寻找“废弃”的交易(带有“错误”标志的记录,并在管理控制台上报告)。