我们有一个PostgreSQL函数已经运行了很长一段时间就好了,但是最近它因为不明原因而开始挂起......
我挖掘了函数,函数的第一行是" lock;"
随着该行的注释,该函数运行得非常好,但允许该表锁运行会导致我的函数,因此我的应用程序无限期地锁定(冻结)......
代码本身有点愚蠢(我们现在只是维护它的遗留代码)...所以请不要问为什么这个代码运行...只是知道它抓取一个唯一的ID用于应用程序中的给定功能集。我也知道,当它用完唯一ID时会出现问题......我们会定期清除这些ID,以便始终有可用的ID。
declare
tmp int4;
begin
lock table1; --the offending line
for g in 1 .. 999 loop
select g_id into tmp from table1 where g_id = g;
if not found then
insert into table1 (g_id, type, date, status) values (g, 'type', current_timestamp, 'w');
return g;
end if;
end loop;
raise exception 'unable to find unique id';
return 0;
end;
再次,没有"锁定"命令,该函数运行,但一旦我允许该命令运行它就会挂起。有没有人看过PostgreSQL的类似问题并有解决方案?
答案 0 :(得分:0)
一旦函数挂起,请查看pg_locks表以查看其中的内容 拿着锁。从那里,你应该能够弄清楚 你的僵局在哪里。请记住锁定一直持续到 交易结束。
由于您正在进行插入操作,因此您需要使用锁来避免竞争 抓住一个免费的id并将其插入表中的条件。 如果应用程序可以处理它,请考虑使用序列 生成ids。
正如“a_horse_with_no_name”所指出的,这是一种可怕的观察方式 换一个新的身份证。 SQL是基于集合设置的,因此使用set操作进行查找 未使用的ids。
举例来说:
首先,测试数据表。你不需要这个,因为你 使用你自己的table1。
create temp table table1 (g_id integer);
insert into table1
select x from generate_series(1,999) x
where random() < 0.10;
获取未使用的ID:
select
generate_series(1,999) new_id
except
select g_id from table1
limit 1;
如果您需要最低的未使用ID,请使用:
with unused as (
select
generate_series(1,999) new_id
except
select g_id from table1
)
select new_id from unused order by new_id limit 1;