Re: DISCARD ALL failing to acquire locks on pg_listen

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Matteo Beccati <php(at)beccati(dot)com>
Cc: Postgres Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: DISCARD ALL failing to acquire locks on pg_listen
Date: 2009-02-12 19:29:56
Message-ID: 15385.1234466996@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Matteo Beccati <php(at)beccati(dot)com> writes:
> Tom Lane ha scritto:
>> This seems a bit overcomplicated. I had in mind something like this...

> Much easier indeed... I didn't notice the unlistenExitRegistered variable.

Just for completeness, I attach another form of the patch that I thought
about for a bit. This adds the ability for UNLISTEN ALL to revert the
backend to the state where subsequent UNLISTENs don't cost anything.
This could be of value in a scenario where you have pooled connections
and just a small fraction of the client threads are using LISTEN. That
seemed like kind of an unlikely use-case though. The problem is that
this patch adds some cycles to transaction commit/abort for everyone,
whether they ever use LISTEN/UNLISTEN/DISCARD or not. It's not a lot of
cycles, but even so I'm thinking it's not a win overall. Comments?

regards, tom lane

Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.272
diff -c -r1.272 xact.c
*** src/backend/access/transam/xact.c 20 Jan 2009 18:59:37 -0000 1.272
--- src/backend/access/transam/xact.c 12 Feb 2009 18:24:12 -0000
***************
*** 1703,1708 ****
--- 1703,1709 ----
AtEOXact_SPI(true);
AtEOXact_xml();
AtEOXact_on_commit_actions(true);
+ AtEOXact_Notify(true);
AtEOXact_Namespace(true);
/* smgrcommit already done */
AtEOXact_Files();
***************
*** 1939,1944 ****
--- 1940,1946 ----
AtEOXact_SPI(true);
AtEOXact_xml();
AtEOXact_on_commit_actions(true);
+ AtEOXact_Notify(true);
AtEOXact_Namespace(true);
/* smgrcommit already done */
AtEOXact_Files();
***************
*** 2084,2089 ****
--- 2086,2092 ----
AtEOXact_SPI(false);
AtEOXact_xml();
AtEOXact_on_commit_actions(false);
+ AtEOXact_Notify(false);
AtEOXact_Namespace(false);
AtEOXact_Files();
AtEOXact_ComboCid();
Index: src/backend/commands/async.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/async.c,v
retrieving revision 1.145
diff -c -r1.145 async.c
*** src/backend/commands/async.c 1 Jan 2009 17:23:37 -0000 1.145
--- src/backend/commands/async.c 12 Feb 2009 18:24:13 -0000
***************
*** 167,172 ****
--- 167,178 ----
/* True if we've registered an on_shmem_exit cleanup */
static bool unlistenExitRegistered = false;

+ /* True if this backend has (or might have) an active LISTEN entry */
+ static bool haveActiveListen = false;
+
+ /* True if current transaction is trying to commit an UNLISTEN ALL */
+ static bool committingUnlistenAll = false;
+
bool Trace_notify = false;


***************
*** 277,282 ****
--- 283,292 ----
if (Trace_notify)
elog(DEBUG1, "Async_Unlisten(%s,%d)", relname, MyProcPid);

+ /* If we couldn't possibly be listening, no need to queue anything */
+ if (pendingActions == NIL && !haveActiveListen)
+ return;
+
queue_listen(LISTEN_UNLISTEN, relname);
}

***************
*** 291,296 ****
--- 301,310 ----
if (Trace_notify)
elog(DEBUG1, "Async_UnlistenAll(%d)", MyProcPid);

+ /* If we couldn't possibly be listening, no need to queue anything */
+ if (pendingActions == NIL && !haveActiveListen)
+ return;
+
queue_listen(LISTEN_UNLISTEN_ALL, "");
}

***************
*** 493,499 ****
heap_freetuple(tuple);

/*
! * now that we are listening, make sure we will unlisten before dying.
*/
if (!unlistenExitRegistered)
{
--- 507,526 ----
heap_freetuple(tuple);

/*
! * Remember that this backend has at least one active LISTEN. Also,
! * this LISTEN negates the effect of any earlier UNLISTEN ALL in the
! * same transaction.
! *
! * Note: it's still possible for the current transaction to fail before
! * we reach commit. In that case haveActiveListen might be uselessly
! * left true; but that's OK, if not optimal, so we don't expend extra
! * effort to cover that corner case.
! */
! haveActiveListen = true;
! committingUnlistenAll = false;
!
! /*
! * Now that we are listening, make sure we will unlisten before dying.
*/
if (!unlistenExitRegistered)
{
***************
*** 569,574 ****
--- 596,608 ----
simple_heap_delete(lRel, &lTuple->t_self);

heap_endscan(scan);
+
+ /*
+ * Remember that we're trying to commit UNLISTEN ALL. Since we might
+ * still fail before reaching commit, we can't reset haveActiveListen
+ * immediately.
+ */
+ committingUnlistenAll = true;
}

/*
***************
*** 675,680 ****
--- 709,730 ----
}

/*
+ * AtEOXact_Notify
+ *
+ * Clean up post-commit or post-abort. This is not called until
+ * we know that we successfully committed (or didn't).
+ */
+ void
+ AtEOXact_Notify(bool isCommit)
+ {
+ /* If we committed UNLISTEN ALL, we can reset haveActiveListen */
+ if (isCommit && committingUnlistenAll)
+ haveActiveListen = false;
+ /* In any case, the next xact starts with clean UNLISTEN ALL slate */
+ committingUnlistenAll = false;
+ }
+
+ /*
* AtSubStart_Notify() --- Take care of subtransaction start.
*
* Push empty state for the new subtransaction.
Index: src/include/commands/async.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/commands/async.h,v
retrieving revision 1.37
diff -c -r1.37 async.h
*** src/include/commands/async.h 1 Jan 2009 17:23:58 -0000 1.37
--- src/include/commands/async.h 12 Feb 2009 18:24:13 -0000
***************
*** 28,33 ****
--- 28,34 ----
extern void AtSubCommit_Notify(void);
extern void AtSubAbort_Notify(void);
extern void AtPrepare_Notify(void);
+ extern void AtEOXact_Notify(bool isCommit);

/* signal handler for inbound notifies (SIGUSR2) */
extern void NotifyInterruptHandler(SIGNAL_ARGS);

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2009-02-12 19:49:41 Re: pg_migrator and handling dropped columns
Previous Message Tom Lane 2009-02-12 19:19:40 Re: GIN fast insert