正如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 postgres
和this
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
答案 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为您节省时间和精力。