PostgreSQL表锁定正在冻结

问题描述 投票:0回答:1

我们有一个PostgreSQL函数已经运行了很长一段时间就好了,但最近它因为未知原因而开始挂起......

我挖掘了函数,函数的第一行是“锁定”;

注释掉该行后,该函数运行得非常好,但允许该表锁运行会导致我的函数,因此我的应用程序无限期地锁定(冻结)...

代码本身有点傻(这是我们刚刚维护的遗留代码)...所以请不要问为什么这个代码运行...只要知道它抓取一个唯一的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;

同样,如果没有“lock”命令,该函数会运行,但是一旦我允许该命令运行它就会挂起。有谁见过PostgreSQL的类似问题并有解决方案?

postgresql
1个回答
0
投票

一旦函数挂起,请查看pg_locks表以查看持有锁的内容。从那里,您应该能够找出死锁的位置。请记住,锁定一直持续到事务结束。

由于您正在进行插入操作,因此需要锁定以避免在获取空闲ID并将其插入表中时出现争用情况。如果应用程序可以处理它,请考虑使用序列来生成id。

正如“a_horse_with_no_name”所指出的,这是一种寻找新id的可怕方式。 SQL是基于集合设置的,因此使用set操作来查找未使用的ID。

举例来说:

首先是测试数据表。你不需要这个,因为你使用自己的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;
© www.soinside.com 2019 - 2024. All rights reserved.