如何列出表的所有锁定行?

Ada*_*ski 6 postgresql locking

我的应用程序使用悲观锁定。当用户打开用于更新记录的表单时,应用程序执行此查询(表名是示例性的):

begin;
select * 
from master m
natural join detail d
where m.master_id = 123456
for update nowait;
Run Code Online (Sandbox Code Playgroud)

该查询锁定一个主行和几个(到几十个)明细行。交易一直持续到用户确认或取消更新。

我需要知道哪些行(至少是主行)被锁定。我挖掘了文档和 postgres wiki 没有成功。

是否可以列出所有锁定的行?

Ste*_*imm 12

PostgreSQL 9.5 添加了一个新选项FOR UPDATE,提供了一种直接的方法来执行此操作。

SELECT master_id
FROM master
WHERE master_id NOT IN (
  SELECT master_id
  FROM master
  FOR UPDATE SKIP LOCKED);
Run Code Online (Sandbox Code Playgroud)

这会获取所有当前未锁定的行的锁,因此请仔细考虑这对您来说是否有问题,尤其是在您的表很大的情况下。如果不出意外,您将希望避免在公开事务中执行此操作。如果你的表很大,你可以应用额外的WHERE条件并分块遍历它以避免一次锁定所有内容。


kli*_*lin 7

是否可以?可能是的,但它是 Postgres 的最大谜团。我认为您需要为它编写自己的扩展 (*)。

但是,有一种简单的方法可以解决此问题。你可以使用非常好的 Postgres 特性,advisory lockspg_try_advisory_lock(key1 int, key2 int)您可以将函数的两个参数解释为:table oid (key1) 和row id (key2)。然后

select pg_try_advisory_lock(('master'::regclass)::integer, 123456)
Run Code Online (Sandbox Code Playgroud)

锁定表master 的第 123456 行,如果之前没有锁定。该函数返回布尔值。

更新后必须释放锁:

select pg_advisory_unlock(('master'::regclass)::integer, 123456)
Run Code Online (Sandbox Code Playgroud)

最好的事情是锁定行列表:

select classid::regclass, objid
from pg_locks
where locktype = 'advisory'
Run Code Online (Sandbox Code Playgroud)

咨询锁可以作为常规锁的补充,或者您可以独立使用它们。第二个选项非常诱人,因为它可以显着简化代码。但是应该谨慎应用它,因为您必须确保所有应用程序中的表上的所有更新(删除)都使用此锁定执行。


(*)石井达夫先生做到了(我不知道,刚刚发现)。