PostgreSQL并选择更新限制
你能给我解释一下这种奇怪的行为吗: 我有一个存储过程,它告诉我一行是否被锁定PostgreSQL并选择更新限制,postgresql,transactions,locking,Postgresql,Transactions,Locking,你能给我解释一下这种奇怪的行为吗: 我有一个存储过程,它告诉我一行是否被锁定 CREATE OR REPLACE FUNCTION tg_availablega_is_unlocked(availablega_id integer) RETURNS boolean AS $BODY$ DECLARE is_locked boolean = FALSE; BEGIN BEGIN PERFORM id FROM tg_availablega WHERE id = avai
CREATE OR REPLACE FUNCTION tg_availablega_is_unlocked(availablega_id integer)
RETURNS boolean AS
$BODY$
DECLARE
is_locked boolean = FALSE;
BEGIN
BEGIN
PERFORM id FROM tg_availablega WHERE id = availablega_id
FOR UPDATE NOWAIT;
EXCEPTION
WHEN lock_not_available THEN
is_locked := TRUE;
END;
RETURN not is_locked;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
如果我启动事务并执行此操作:
SELECT "tg_availablega"."id",
"tg_availablega"."isactive",
"tg_availablega"."schedule",
"tg_availablega"."zone_tg_id"
FROM "tg_availablega"
WHERE (tg_availablega_is_unlocked("tg_availablega"."id")
AND "tg_availablega"."zone_tg_id" = 1
AND "tg_availablega"."isactive" = TRUE
AND "tg_availablega"."schedule" = 20)
LIMIT 100
FOR
UPDATE;
它锁定并返回100行。如果我在其他事务中同时执行相同的操作,它将锁定并返回不同的100行。如果行总数为101,则第一次执行返回100行,第二次执行只返回剩余的1行
但是如果我加上ORDERBY条款
SELECT "tg_availablega"."id",
"tg_availablega"."isactive",
"tg_availablega"."schedule",
"tg_availablega"."zone_tg_id"
FROM "tg_availablega"
WHERE (tg_availablega_is_unlocked("tg_availablega"."id")
AND "tg_availablega"."zone_tg_id" = 1
AND "tg_availablega"."isactive" = TRUE
AND "tg_availablega"."schedule" = 20)
***ORDER BY "tg_availablega"."id"***
LIMIT 100
FOR
UPDATE;
然后,第一个事务返回100个锁定行,第二个事务不返回任何行
为什么会这样?问题在于函数tg\u availablega\u is\u unlocked会锁定它检查的行。没有order by,Postgres不会访问所有行,因此不会对所有行调用该函数。我想你的意思是:
select * from (
SELECT "tg_availablega"."id",
"tg_availablega"."isactive",
"tg_availablega"."schedule",
"tg_availablega"."zone_tg_id"
FROM "tg_availablega"
WHERE "tg_availablega"."zone_tg_id" = 1
AND "tg_availablega"."isactive" = TRUE
AND "tg_availablega"."schedule" = 20)
ORDER BY "tg_availablega"."id"
) a
where tg_availablega_is_unlocked(id)
limit 100
问题是函数tg_availablega_is_unlocked会锁定它检查的行。没有order by,Postgres不会访问所有行,因此不会对所有行调用该函数。我想你的意思是:
select * from (
SELECT "tg_availablega"."id",
"tg_availablega"."isactive",
"tg_availablega"."schedule",
"tg_availablega"."zone_tg_id"
FROM "tg_availablega"
WHERE "tg_availablega"."zone_tg_id" = 1
AND "tg_availablega"."isactive" = TRUE
AND "tg_availablega"."schedule" = 20)
ORDER BY "tg_availablega"."id"
) a
where tg_availablega_is_unlocked(id)
limit 100