I am trying to perform DELETE
and INSERT
statements in a trigger function, like
BEGIN
IF (TG_OP = 'DELETE') THEN
DELETE FROM…;
INSERT INTO…;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE' OR TG_OP = 'INSERT') THEN
DELETE FROM…;
INSERT INTO…;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
but as trigger execution is synchronous, the performance of each statement will be bad, so I need to have the statements in the trigger function to be performed asynchronously. I had found some approaches like dblink and pg_background. In dblink, PostgreSQL creates a new connection, which also does not suit for my use case, and it also takes long, so I dropped it.
I tried pg_background to achieve asynchronous execution like
DECLARE
result text;
BEGIN
IF (TG_OP = 'DELETE') THEN
SELECT * FROM pg_background_result(pg_background_launch(sql_command)) AS (result TEXT) INTO result;
SELECT * FROM pg_background_result(pg_background_launch(sql_command)) as (result TEXT) INTO result;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE' OR TG_OP = 'INSERT') THEN
SELECT * FROM pg_background_result(pg_background_launch(sql_command)) as (result TEXT) INTO result;
SELECT * FROM pg_background_result(pg_background_launch(sql_command)) as (result TEXT) INTO result;
RETURN NEW;
END IF;
RETURN NULL; -- result is ignored since this is an AFTER trigger
END;
Here we are also facing performance issues. PostgreSQL consumes more time than with direct synchronous statements.
Is this approach correct for my use case? How can I achieve it using some other approach?
I had tried with LISTEN
and NOTIFY
using pg_notify()
, but I can’t listen and perform additional statements inside Postgres itself, so I have written a Java application to listen for this notification and perform the statements asynchronously. That is working fine, but I need to reduce the external dependencies here.
This is a late reply but if it is still relevant: Running
PERFORM pg_background_launch(sql_command)
does indeed make it run async.
However, function
SELECT * FROM pg_background_result()
you are using is awaiting for the result of the async task. That makes you trigger syncronous. If you do not need the result of the async task, you can just use pg_background_launch query. However if you will later need the results of the query, i could suggest creating a table for the results and altering sql_command so that it would insert it's result into that table.