PostgreSQL表锁定正在冻结

时间:2018-03-01 17:29:45

标签: postgresql

我们有一个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的类似问题并有解决方案?

1 个答案:

答案 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;