乐观锁队列
Optimistic locking queue
我正在 Node.js 中使用 PostgreSQL 作为数据库编写应用程序。但是我有一些问题。
我有一个 table,其中包含有关区域资源的信息:
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 的当前值非常重要,并且首先点击的用户应该使用最大值,我如何使用乐观锁定在没有锁定的情况下做到这一点。可用 current_resource。换句话说,我应该为 current_resource 实现访问队列。
对于乐观锁定,您需要定义一些方法来检查某行自您上次看到它以来是否发生了更改。例如,让我们再添加一个标识符:
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;
但是乐观锁在高并发的情况下效果不佳。当冲突并不少见时,您将不得不频繁地重新启动事务。
我正在 Node.js 中使用 PostgreSQL 作为数据库编写应用程序。但是我有一些问题。 我有一个 table,其中包含有关区域资源的信息:
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 的当前值非常重要,并且首先点击的用户应该使用最大值,我如何使用乐观锁定在没有锁定的情况下做到这一点。可用 current_resource。换句话说,我应该为 current_resource 实现访问队列。
对于乐观锁定,您需要定义一些方法来检查某行自您上次看到它以来是否发生了更改。例如,让我们再添加一个标识符:
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;
但是乐观锁在高并发的情况下效果不佳。当冲突并不少见时,您将不得不频繁地重新启动事务。