diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-05-23 03:50:45 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-05-23 03:50:45 +0000 |
commit | ebfc56d3fb41d914c799555a1f4c9d1a72379e9f (patch) | |
tree | 7fb674efed5b26eb9a11b0e77733b2c8e7eaf642 /src/backend/commands/async.c | |
parent | 4d86ae42600c42834a55371630416e98593b7b11 (diff) | |
download | postgresql-ebfc56d3fb41d914c799555a1f4c9d1a72379e9f.tar.gz postgresql-ebfc56d3fb41d914c799555a1f4c9d1a72379e9f.zip |
Handle impending sinval queue overflow by means of a separate signal
(SIGUSR1, which we have not been using recently) instead of piggybacking
on SIGUSR2-driven NOTIFY processing. This has several good results:
the processing needed to drain the sinval queue is a lot less than the
processing needed to answer a NOTIFY; there's less contention since we
don't have a bunch of backends all trying to acquire exclusive lock on
pg_listener; backends that are sitting inside a transaction block can
still drain the queue, whereas NOTIFY processing can't run if there's
an open transaction block. (This last is a fairly serious issue that
I don't think we ever recognized before --- with clients like JDBC that
tend to sit with open transaction blocks, the sinval queue draining
mechanism never really worked as intended, probably resulting in a lot
of useless cache-reset overhead.) This is the last of several proposed
changes in response to Philip Warner's recent report of sinval-induced
performance problems.
Diffstat (limited to 'src/backend/commands/async.c')
-rw-r--r-- | src/backend/commands/async.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 5233e781789..15d7c0aae5c 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.110 2004/05/22 21:58:24 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.111 2004/05/23 03:50:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -86,6 +86,7 @@ #include "libpq/pqformat.h" #include "miscadmin.h" #include "storage/ipc.h" +#include "storage/sinval.h" #include "tcop/tcopprot.h" #include "utils/fmgroids.h" #include "utils/ps_status.h" @@ -607,7 +608,7 @@ AtAbort_Notify(void) /* *-------------------------------------------------------------- - * Async_NotifyHandler + * NotifyInterruptHandler * * This is the signal handler for SIGUSR2. * @@ -623,7 +624,7 @@ AtAbort_Notify(void) *-------------------------------------------------------------- */ void -Async_NotifyHandler(SIGNAL_ARGS) +NotifyInterruptHandler(SIGNAL_ARGS) { int save_errno = errno; @@ -669,12 +670,12 @@ Async_NotifyHandler(SIGNAL_ARGS) { /* Here, it is finally safe to do stuff. */ if (Trace_notify) - elog(DEBUG1, "Async_NotifyHandler: perform async notify"); + elog(DEBUG1, "NotifyInterruptHandler: perform async notify"); ProcessIncomingNotify(); if (Trace_notify) - elog(DEBUG1, "Async_NotifyHandler: done"); + elog(DEBUG1, "NotifyInterruptHandler: done"); } } @@ -766,12 +767,20 @@ EnableNotifyInterrupt(void) * This is called by the PostgresMain main loop just after receiving * a frontend command. Signal handler execution of inbound notifies * is disabled until the next EnableNotifyInterrupt call. + * + * The SIGUSR1 signal handler also needs to call this, so as to + * prevent conflicts if one signal interrupts the other. So we + * must return the previous state of the flag. * -------------------------------------------------------------- */ -void +bool DisableNotifyInterrupt(void) { + bool result = (notifyInterruptEnabled != 0); + notifyInterruptEnabled = 0; + + return result; } /* @@ -785,10 +794,6 @@ DisableNotifyInterrupt(void) * and clear the notification field in pg_listener until next time. * * NOTE: since we are outside any transaction, we must create our own. - * - * Results: - * XXX - * * -------------------------------------------------------------- */ static void @@ -803,11 +808,15 @@ ProcessIncomingNotify(void) Datum value[Natts_pg_listener]; char repl[Natts_pg_listener], nulls[Natts_pg_listener]; + bool catchup_enabled; + + /* Must prevent SIGUSR1 interrupt while I am running */ + catchup_enabled = DisableCatchupInterrupt(); if (Trace_notify) elog(DEBUG1, "ProcessIncomingNotify"); - set_ps_display("async_notify"); + set_ps_display("notify interrupt"); notifyInterruptOccurred = 0; @@ -883,6 +892,9 @@ ProcessIncomingNotify(void) if (Trace_notify) elog(DEBUG1, "ProcessIncomingNotify: done"); + + if (catchup_enabled) + EnableCatchupInterrupt(); } /* |