【发布时间】:2009-05-31 08:30:55
【问题描述】:
我试图想出一种有效的方法来让一群人完成一系列数据输入任务。以前我们只有一个人这样做,所以这不是问题。后端是 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;
这意味着可以为两个用户分配相同的记录进行编辑,我们支持第一个提交的用户,在随后的提交中静默失败,例如:
- 用户 A 加载记录 321 进行编辑
- 用户 B 加载记录 321 进行编辑
- 用户 B 提交更改(它们保存在数据库中)
- 用户 A 提交更改(未保存在数据库中)
(注意:我们可以信任所有用户提交可接受的数据,因此我们无需保留来自第二个UPDATE 的数据。)
这种方法的问题是,当用户同时开始并以大致相同的速度进行编辑时,他们通常会更新相同的记录,但只有其中一条记录被保存。换句话说,浪费了大量的工时。我可以通过选择随机行在一定程度上缓解这种情况,但我更喜欢更有保证的东西。
这就是我的想法......
有一个表叫: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 继续更新锁,如果结果证明是有利的。
任何人都可以对此提出想法吗?听起来像是一种很好的做事方式?听起来像一个可怕的方式?以前做过这个?我很想听听一些反馈。
谢谢! J
【问题讨论】:
标签: sql concurrency locking