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

时间:2014-05-24 19:02:12

标签: postgresql locking

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

begin;
select * 
from master m
natural join detail d
where m.master_id = 123456
for update nowait;

查询锁定一个主行和几个(几十个)详细信息行。交易开放,直到用户确认或取消更新。

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

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

2 个答案:

答案 0 :(得分:3)

有可能吗?可能是的,但它是Postgres的最大谜团。我想你需要为它编写自己的扩展名(*)。

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

select pg_try_advisory_lock(('master'::regclass)::integer, 123456)

锁定表 master 的行123456(如果它之前未锁定)。该函数返回布尔值。

更新后,必须释放锁定:

select pg_advisory_unlock(('master'::regclass)::integer, 123456)

最好的东西,锁定行列表:

select classid::regclass, objid
from pg_locks
where locktype = 'advisory'

咨询锁可能是常规锁的补充,也可以单独使用。第二个选项非常具有临界性,因为它可以显着简化代码。但是应该谨慎应用,因为您必须确保所有应用程序中的表上的所有更新(删除)都是通过此锁定来执行的。


(*)Mr. Tatsuo Ishii做了(我不知道,刚发现)。

答案 1 :(得分:3)

PostgreSQL 9.5为FOR UPDATE添加了一个新选项,提供了一种直接的方法。

SELECT master_id
FROM master
WHERE master_id NOT IN (
  SELECT master_id
  FROM master
  FOR UPDATE SKIP LOCKED);

这会锁定所有当前未锁定的行,因此请考虑一下这是否对您有用,尤其是在您的表很大的情况下。如果不出意外,您将要避免在开放交易中这样做。如果您的表格很大,您可以应用其他WHERE条件并以块的形式逐步执行,以避免一次锁定所有内容。