Re: backend dies suddenly after a lot of error messages - Mailing list pgsql-general

From Tom Lane
Subject Re: backend dies suddenly after a lot of error messages
Date
Msg-id 14059.926644574@sss.pgh.pa.us
Whole thread Raw
In response to backend dies suddenly after a lot of error messages  (Mirko Kaffka <mirko@interface-business.de>)
List pgsql-general
Mirko Kaffka <mirko@interface-business.de> wrote:
> We have problems with backend processes that close the channel because of
> palloc() failures. When an INSERT statement fails, the backend reports an
> error (e.g. `Cannot insert a duplicate key into a unique index') and
> allocates a few bytes more memory. The next SQL statement that fails
> causes the backend to allocate more memory again, etc. until we have no
> more virtual memory left. Is this a bug?
> We are using postgres 6.4.2 on FreeBSD 2.2.8.

I have found the primary cause of memory leakage after an error ---
basically, the backend forgets to free *any* of the temporary memory
allocated up to the point of the error :-(.  If your applications tend
to provoke many SQL errors then you will see a backend process that eats
up more and more memory until it hits your local system's process size
limit, whereupon it crashes.

I have repaired this problem in the 6.5 development sources.  Attached
is a patch for 6.4.2, which I suggest you apply if this sounds like a
problem you are having.

The patch does not completely eliminate memory leaks after errors, but
they seem to be reduced to the few-hundred-bytes-per-error range instead
of the kilobytes (potentially lots of kilobytes) range.  I am working on
curing the problem more completely for 6.5.

            regards, tom lane

*** src/backend/access/transam/xact.c.orig    Thu Oct  8 14:29:15 1998
--- src/backend/access/transam/xact.c    Thu May 13 18:53:05 1999
***************
*** 767,776 ****
  static void
  AtAbort_Memory()
  {
      /* ----------------
!      *    after doing an abort transaction, make certain the
!      *    system uses the top memory context rather then the
!      *    portal memory context (until the next transaction).
       * ----------------
       */
      MemoryContextSwitchTo(TopMemoryContext);
--- 767,791 ----
  static void
  AtAbort_Memory()
  {
+     Portal        portal;
+     MemoryContext portalContext;
+
      /* ----------------
!      *    Release memory in the blank portal.
!      *  Since EndPortalAllocMode implicitly works on the current context,
!      *  first make real sure that the blank portal is the selected context.
!      *  (This is ESSENTIAL in case we aborted from someplace where it wasn't.)
!      * ----------------
!      */
!     portal = GetPortalByName(NULL);
!     portalContext = (MemoryContext) PortalGetHeapMemory(portal);
!     MemoryContextSwitchTo(portalContext);
!     EndPortalAllocMode();
!
!     /* ----------------
!      *    Now that we're "out" of a transaction, have the
!      *    system allocate things in the top memory context instead
!      *    of the blank portal memory context.
       * ----------------
       */
      MemoryContextSwitchTo(TopMemoryContext);

pgsql-general by date:

Previous
From: Brian
Date:
Subject: postgres getting slow
Next
From: Doo Suk Yang
Date:
Subject: Re: [GENERAL] How to express categorized items in relational tables