乐观锁定队列

时间:2016-01-17 02:11:21

标签: postgresql transactions

我正在使用PostgreSQL作为数据库在Node.js中编写应用程序。但我有一些问题。 我有一张表格,里面有关于地区资源的信息:

CREATE TABLE regions_indexes
(
  id integer NOT NULL,
  resource_type integer NOT NULL,
  current_resource integer,
  maximum_resource integer,
  CONSTRAINT regions_indexes_pkey PRIMARY KEY (id, resource_type)
)

用户点击按钮,应用程序根据current_resource计算各种参数,然后执行current_resource - $ calc_value。因为它可能非常简洁地使用交易。但在过程计算中可能存在一些错误,我们需要重复计算。现在我使用SELECT ... FOR UPDATE来使用current_resource来锁定行。如果current_resource的当前值非常重要,并且首先点击的用户应该使用max,那么我如何使用乐观锁定无锁定。 avalaible current_resource。换句话说,我应该为current_resource实现一个访问队列。

1 个答案:

答案 0 :(得分:1)

对于乐观锁定,您需要定义一些方法来检查自上次查看以来行是否已更改。例如,我们只需添加另一个标识符:

alter table regions_indexes add version_id integer default 1 not null;

现在应用程序读取一些行,向用户显示数据并等待直到单击按钮。我们必须记住我们得到的version_id的价值。

单击按钮后,将执行所有必要的计算。当您准备好更新该行时,您将锁定该行并检查version_id是否未更改。如果没有,请递增version_id并提交。如果有,运气不好---你需要告诉用户重复操作,因为有人超过了他。

它可能看起来像这样(伪代码):

-- remember version_id
select *
from regions_indexes
where id = ... and resource_type = ...;

-- wait for user click
-- you can wait for a long time, because no lock is yet acquired
...

update regions_indexes
set current_resource = current_resource - ..., version_id = version_id + 1
where id = ... and resource_type = ...
returning version_id;

if new_version_id = old_version_id + 1 then
  -- success, commit
else 
  -- fail, rollback
end if;

但乐观锁定在高并发性的情况下不能很好地工作。当冲突不常见时,您将不得不经常重启事务。