1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

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.
This commit is contained in:
Tom Lane
2004-05-23 03:50:45 +00:00
parent 4d86ae4260
commit ebfc56d3fb
8 changed files with 289 additions and 37 deletions

View File

@ -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();
}
/*