postgres pg_try_advisory_lock和限制问题

时间:2011-01-02 20:23:15

标签: postgresql locking

正如http://www.postgresql.org/docs/8.2/interactive/explicit-locking.html中所述,在锁定行之前不会有应用限制。虽然pg_try_advisory_lock上的包装器应该可以工作但不起作用。

以下代码只锁定一行。如果从其他实例执行相同的代码而不是锁定未锁定的行,则它会尝试锁定已锁定的第一个ID并返回false。

参考:http://www.flyingtealeaf.com/2010/02/17/postgresql-concurrency
lock the rows until next select postgresthis

select pg_try_advisory_lock(id), * 
from 
( 
  select  id,val
from test
left JOIN pg_locks pgl
       ON pgl.classid = tableoid('test')
      AND pgl.objid = test.id
      AND pgl.pid <> pg_backend_pid()

    WHERE pgl.objid IS NULL
order by id limit 1
) t

2 个答案:

答案 0 :(得分:3)

据我所知,您正在尝试获取尚未使用咨询锁标记的第一行的建议锁。

编辑:在尝试这个之后,内部选择中的pg_try_advisory_lock()显然不起作用(应该先考虑过)。但是通过检查objid只是从表中排除所有行应该有效:

select pg_try_advisory_lock(id), * 
from 
( 
  select  id,val
  from test
  where id not in (select objid from pg_locks where locktype = 'advisory')
  order by id limit 1
) t

修改

虽然顾问锁将显示在pg_locks中,但它们永远不会有关于已被锁定的表或行的任何信息。毕竟pg_advisory_lock()只是传递了一个与基础表或行没有连接的数字。

SELECT pg_advisory_lock(42)

将创建与

完全相同的咨询锁
SELECT pg_advisory_lock(id) 
FROM foo 
WHERE id = 42

所以使用classid的连接永远不会成功。

答案 1 :(得分:0)

抱歉我的错误。我应该逐行完成第一个参考链接。作者正在做的伎俩就是在调用锁定函数的同时设置classid。最后的代码最终用于LIMIT

select pg_try_advisory_lock(tableoid('test'),id) , * from
(
select  id,val
from test
LEFT JOIN pg_locks pgl
       ON pgl.classid = tableoid('test')
      AND pgl.objid = test.id
      AND pgl.pid <> pg_backend_pid()

    WHERE pgl.objid IS NULL
order by id    limit 1)f

Tableoid函数(从ref#1复制)

CREATE OR REPLACE FUNCTION tableoid(tablename TEXT) RETURNS INTEGER AS $$
BEGIN
  RETURN (SELECT oid FROM pg_class WHERE relname = tablename);
END
$$
LANGUAGE plpgsql IMMUTABLE SECURITY DEFINER;

比你 a_horse_with_no_name为您节省时间和精力。