Re: Trigger concurrent execution

From: Craig Ringer <craig(at)2ndquadrant(dot)com>
To: Blagoj Petrushev <b(dot)petrushev(at)gmail(dot)com>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: Trigger concurrent execution
Date: 2014-05-16 05:55:50
Message-ID: 5375A866.2060100@2ndquadrant.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 05/16/2014 08:06 AM, Blagoj Petrushev wrote:
> Hi,
>
> I'm thinking of an extension to trigger functionality like this:
>
> CREATE TRIGGER trigger_name
> AFTER event
> ON table
> CONCURRENTLY EXECUTE PROCEDURE trigger_fc
>
> This would call the trigger after the end of the transaction.

If "after the end of the transaction" is what you mean by
"concurrently", then that's the wrong word to choose.

"AFTER COMMIT" ?

The concept of running a trigger "concurrently" just doesn't make sense
in PostgreSQL, because the backend is single threaded. You wouldn't be
able to run any SQL commands until the trigger finished.

It isn't possible to do anything useful without a transaction, so
PostgreSQL would need to start a transaction for the trigger and commit
the transaction at the end, as if you'd run SELECT my_procedure();.
Because it's outside the scope of the transaction it probably wouldn't
be possible to do FOR EACH ROW with a NEW and OLD var, unless you
stashed them as materialized rows in the queue of pending "AFTER COMMIT"
triggers.

Finally, because it's after transaction commit, you couldn't easily
guarantee that the trigger would really run. If the backend crashed /
the server was shut down / etc after the commit but before your trigger
finished, you'd have a committed transaction but the trigger would not
run. To fix that you'd need to somehow make the trigger queue WAL-logged
and run it during replay, which from my rather limited understanding of
this area would be ... "interesting" to do. It'd also mean the trigger
couldn't have any session context.

This isn't easy, if it's practical at all.

> I have a big table with big text column article and a nullable
> tsvector column fts_article. On each insert or update that changes the
> article, I trigger-issue 'NOTIFY article_changed row_id', then, with a
> daemon listener, I catch the notification and update fts_article
> accordingly with my_fts_fc(article). The reason I don't do this
> directly in my trigger is because my_fts_fc is slow for big articles,
> fts_article has a gin index, and also, on heavy load, my listener can
> do these updates concurrently. Now, with a concurrent execution of
> triggers, I can just call my_fts_fc inside the trigger instead of the
> notify roundtrip.

I don't think that really fits.

It seems like you want to run the trigger procedure in the background on
another back-end. That'd be quite cool, but also not trivial to do,
especially if you wanted to guarantee that it happened reliably and in a
crash-safe manner.

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Heikki Linnakangas 2014-05-16 07:26:01 Re: sepgsql: label regression test failed
Previous Message Craig Ringer 2014-05-16 05:38:34 BUGFIX: Dynamic bgworkers with BGW_NEVER_RESTART worker restarted on FatalError