【问题标题】:Lock row, release later锁定行,稍后释放
【发布时间】:2019-11-15 10:08:48
【问题描述】:

我正在尝试了解如何锁定一行,然后才释放该锁定。

我有一张这样的桌子:

create table testTable (Name varchar(100));

一些测试数据

insert into testTable (name) select 'Bob';
insert into testTable (name) select 'John';
insert into testTable (name) select 'Steve';

现在,我想选择其中一行,并阻止其他查询看到这一行。我是这样实现的:

begin transaction;
select * from testTable where name = 'Bob' for update;

在另一个窗口中,我这样做:

select * from testTable for update skip locked;

太好了,我在该结果集中没有看到“Bob”。现在,我想对检索到的主要行 (Bob) 做一些事情,在我完成工作之后,我想再次释放该行。简单的答案是: 提交事务

但是,我在同一个连接上运行多个事务,所以我不能在整个节目中开始并提交事务。理想情况下,我希望进行“命名”交易,例如:

begin transaction 'myTransaction';
select * from testTable where name = 'Bob' for update;
//do stuff with the data, outside sql then later call ...
commit transaction 'myTransaction';

但是 postgres 不支持。我找到了“准备交易”,但这似乎是一条我不想走下去的梨形路径,尤其是这些交易似乎在重启后仍然存在。

我是否可以参考特定事务的提交/回滚?

【问题讨论】:

    标签: postgresql transactions


    【解决方案1】:

    一个数据库会话中只能有一个事务,所以这个问题没有实际意义。

    但我假设您并不是真的想运行事务,而是想暂时阻止对某行的访问。

    出于这样的目的使用常规数据库锁通常不是一个好主意(咨询锁例外,它完全用于该目的,但不绑定到表行)。问题是长时间的数据库事务使 autovacuum 无法正常工作。

    我建议您在表中添加一个status 列并更改状态而不是锁定该行。这将以更自然的方式实现相同的目的,让您的问题消失。

    如果您担心 status 标志可能由于应用程序逻辑问题而无法清除,请将其替换为 timestamp with time zone 类型的 visible_from 列,该列最初包含 -infinity。将值设置为current_timestamp + INTERVAL '5 minutes',而不是锁定行。只选择满足WHERE visible_from < current_timestamp 的行。这样“锁定”将在 5 分钟后自动过期。

    【讨论】:

    • 我最初也考虑拥有一个状态列,这是做这类事情的标准方式。问题是,这是该解决方案的第二次迭代,我们已经在之前的版本中被烧毁,行会“卡住”(进程在变回状态之前死亡),所以我们试图远离那。我得再四处看看。
    • 我已经用一个想法扩展了答案。
    • 我很高兴看到我们提出了相同的想法!我也在一次会议上提出了这个建议,在行上有某种类型的“到期”,但这个想法并没有得到团队负责人的认可。
    • 好吧,那么团队负责人必须确切地定义他们想要什么,如果需要,您可以在此处exaclty问这个问题。跨度>
    猜你喜欢
    • 2020-12-13
    • 1970-01-01
    • 2019-07-03
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 2021-04-12
    • 2018-11-13
    • 1970-01-01
    相关资源
    最近更新 更多