首页 > 解决方案 > 锁定行,稍后释放

问题描述

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

我有一张这样的桌子:

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 不支持这一点。我找到了“准备交易”,但这似乎是一条我不想走的梨形路径,特别是因为这些交易似乎在重启后仍然存在。

无论如何我可以参考特定事务的提交/回滚吗?

标签: postgresqltransactions

解决方案


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

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

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

我建议您status向表中添加一列并更改状态而不是锁定行。这将以更自然的方式达到相同的目的,并使您的问题消失。

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


推荐阅读