将数据输入任务分配给多个并发Web应用程序用户

时间:2009-05-31 08:30:55

标签: sql concurrency locking

我正在尝试考虑一种允许一群人通过数据输入任务队列工作的有效方法。以前我们只有一个人这样做,所以这不是一个问题。后端是RDBMS,前端是Web应用程序。

目前我们这样做:

指定要编辑的记录:

SELECT * FROM records WHERE in_edit_queue LIMIT 1;

然后,

要保存对以前分配的记录的更改:

UPDATE records SET ..., in_edit_queue = false
  WHERE id = ? AND in_edit_queue = true;

这意味着可以为两个用户分配相同的记录进行编辑,我们赞成提交的第一个用户,在后续提交时无声地失败,例如:

  1. 用户A加载记录321以进行编辑
  2. 用户B加载记录321进行编辑
  3. 用户B提交更改(它们保存在数据库中)
  4. 用户A提交更改(它们未保存在数据库中)
  5. (注意:我们可以信任所有用户提交可接受的数据,因此我们无需保留第二个UPDATE的数据。)

    此方法的问题是当用户同时启动并以大致相同的速度编辑时,他们通常会更新相同的记录,但只会保存其中的1个。换句话说,浪费了大量的工时。我可以通过选择随机行来在某种程度上缓解这种情况,但我更喜欢更有保障的东西。

    所以这就是我在想的......

    有一个名为locked_records (record_id integer, locked_until timestamp)

    的表格
    -- Assign a record for editing:
    -- Same as before but also make sure the
    -- record is not listed in locked_records...
    SELECT * FROM records
      WHERE in_edit_queue AND id NOT IN (
        SELECT record_id FROM locked_records
        WHERE locked_until > now() )
      LIMIT 1;
    
    -- ..and effectively remove it from
    -- the queue for the next 5 minutes
    INSERT INTO locked_records (record_id, locked_until)
      VALUES (?, now() + 300);
    

    然后:

    UPDATE records SET ..., in_edit_queue = false
      WHERE id = ? AND in_edit_queue = true;
    DELETE FROM locked_records WHERE record_id = ?;
    

    典型的编辑需要大约30秒到1分钟,队列中的5分钟应该是一个很好的数量。我还可以在网络应用上使用XHR,如果结果证明是有利的话,请继续更新锁。

    有人能提出这方面的想法吗?听起来像一个好的做事方式?听起来像一个可怕的方式?以前做过这个吗?我很乐意听到一些反馈。

    谢谢! Ĵ

2 个答案:

答案 0 :(得分:0)

RDBMSes内部锁定列表怎么样?将SELECT语句改为SELECT FOR UPDATE会是一个选项吗?

答案 1 :(得分:0)

另一个想法:这些记录还有两列:assigned_to和completed。

当有人想要编辑记录时,请执行

之类的操作
update records set assigned_to = ? # assigning to 'me'
where assigned_to is null
and completed = false
limit 1 # only assign one record at a time

然后,要回到那一行:

select ...
from records
where assigned_to = ? # assigned to 'me'
and completed = false

完成后,将完成设置为'true'。

你可以有一个额外的时间戳列,用于何时将记录分配给某人,然后在上面的更新语句中的where子句的“assigned_to is null”部分添加一个OR替代,在这里你需要一个特定的句子作业有效。