I have a database function I have written to atomize a simple table update. My system is status driven, so I want the next row with the desired status, and update it to a new status, and return the ID.
CREATE OR REPLACE FUNCTION public.processnextid(prevstatus text, nextstatus text)
RETURNS integer
LANGUAGE plpgsql
AS $function$
declare PacketID int4;
BEGIN
SELECT p.id INTO PacketID FROM packet p WHERE p.status = prevStatus limit 1 for update;
UPDATE packet p1 set status = nextStatus WHERE p1.id = PacketID;
RETURN PacketID;
commit;
END;
$function$;
I have several (16) python processes that randomly call this function. The system runs in the background so it's a little had to get an exact play by play, but after several hours of processing I find that some of my processes have stalled. When I query the database for transactional status of the table I find transactions with status "Idle in transaction". I assume that they are waiting for something? I tried to make this function as simple and as quick as possible. Any ideas what the problem might be? How to proceed?
I've looked around the Internet. The examples of select for update I have found are almost exactly the same. So I'm kind of baffled.
pg_locksto find out who's waiting on what. – mustaccio Apr 18 '23 at 16:15commitwould throw an exceptionERROR: invalid transaction termination. So that can't be the function your are running. Show what you really have. Always your version of Postgres. And define what "the next row" means exactly. Can it be any arbitrary qualifying row that's not locked, yet? That's the pivotal point of the task. – Erwin Brandstetter Apr 19 '23 at 01:23