Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bgsV1-0003qB-LD for pgsql-hackers@arkaria.postgresql.org; Mon, 05 Sep 2016 11:55:40 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1bgsV1-0004lD-3A for pgsql-hackers@arkaria.postgresql.org; Mon, 05 Sep 2016 11:55:39 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bgsTb-0002li-GP for pgsql-hackers@postgresql.org; Mon, 05 Sep 2016 11:54:11 +0000 Received: from newmail.postgrespro.ru ([93.174.131.138] helo=mail.postgrespro.ru) by magus.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bgsTX-0001vf-Gq for pgsql-hackers@postgresql.org; Mon, 05 Sep 2016 11:54:10 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.postgrespro.ru (Postfix) with ESMTP id 492F321C27A9 for ; Mon, 5 Sep 2016 14:54:06 +0300 (MSK) X-Virus-Scanned: Debian amavisd-new at postgrespro.ru Received: from mail.postgrespro.ru ([127.0.0.1]) by localhost (mail.postgrespro.ru [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KWXruPh1ghEq for ; Mon, 5 Sep 2016 14:54:06 +0300 (MSK) Received: from [192.168.27.190] (unknown [192.168.27.1]) by mail.postgrespro.ru (Postfix) with ESMTPSA id 1FBBC21C279B for ; Mon, 5 Sep 2016 14:54:06 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mail; t=1473076446; bh=XEXEyoolHZkbWJPvuW4j86OBiGH9+tAjV+hRPv+8m8Y=; h=To:From:Subject:Date; b=QDyuBGWA9HPD30BDggLrOmKs4yZm/90t8rGYJ3+MvA9GOXqWtzEf86nT24AbQoUIU Dso9WUhkGPVjOlZ/4FTvPNyxbVGxiIwlL1hx5I8AIi2c009kNXruQaJ2jtU94Ekdm6 jihXO/aNwBTJ5xBKvfGQFilIslKlpovFSYmQHTEo= To: pgsql-hackers@postgresql.org From: Grigory Smolkin Subject: Fun fact about autovacuum and orphan temp tables Message-ID: <7b7f3e98-9753-3fa9-aaa4-b6f8a766c251@postgrespro.ru> Date: Mon, 5 Sep 2016 14:54:05 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="------------1509A57DCE8E829C22953273" X-Pg-Spam-Score: -3.1 (---) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org This is a multi-part message in MIME format. --------------1509A57DCE8E829C22953273 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Hello, hackers! We were testing how well some application works with PostgreSQL and stumbled upon an autovacuum behavior which I fail to understand. Application in question have a habit to heavily use temporary tables in funny ways. For example it creates A LOT of them. Which is ok. Funny part is that it never drops them. So when backend is finally terminated, it tries to drop them and fails with error: FATAL: out of shared memory HINT: You might need to increase max_locks_per_transaction If I understand that rigth, we are trying to drop all these temp tables in one transaction and running out of locks to do so. After that postgresql.log is flooded at the rate 1k/s with messages like that: LOG: autovacuum: found orphan temp table "pg_temp_15"."tt38147" in database "DB_TEST" It produces a noticeable load on the system and it`s getting worst with every terminated backend or restart. I did some RTFS and it appears that autovacuum has no intention of cleaning that orphan tables unless it`s wraparound time: src/backend/postmaster/autovacuum.c /* We just ignore it if the owning backend is still active */ 2037 if (backendID == MyBackendId || BackendIdGetProc(backendID) == NULL) 2038 { 2039 /* 2040 * We found an orphan temp table (which was probably left 2041 * behind by a crashed backend). If it's so old as to need 2042 * vacuum for wraparound, forcibly drop it. Otherwise just 2043 * log a complaint. 2044 */ 2045 if (wraparound) 2046 { 2047 ObjectAddress object; 2048 2049 ereport(LOG, 2050 (errmsg("autovacuum: dropping orphan temp table \"%s\".\"%s\" in database \"%s\"", 2051 get_namespace_name(classForm->relnamespace), 2052 NameStr(classForm->relname), 2053 get_database_name(MyDatabaseId)))); 2054 object.classId = RelationRelationId; 2055 object.objectId = relid; 2056 object.objectSubId = 0; 2057 performDeletion(&object, DROP_CASCADE, PERFORM_DELETION_INTERNAL); 2058 } 2059 else 2060 { 2061 ereport(LOG, 2062 (errmsg("autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"", 2063 get_namespace_name(classForm->relnamespace), 2064 NameStr(classForm->relname), 2065 get_database_name(MyDatabaseId)))); 2066 } 2067 } 2068 } What is more troubling is that pg_statistic is starting to bloat badly. LOG: automatic vacuum of table "DB_TEST.pg_catalog.pg_statistic": index scans: 0 pages: 0 removed, 68225 remain, 0 skipped due to pins tuples: 0 removed, 2458382 remain, 2408081 are dead but not yet removable buffer usage: 146450 hits, 31 misses, 0 dirtied avg read rate: 0.010 MB/s, avg write rate: 0.000 MB/s system usage: CPU 3.27s/6.92u sec elapsed 23.87 sec What is the purpose of keeping orphan tables around and not dropping them on the spot? -- Grigory Smolkin Postgres Professional: http://www.postgrespro.com The Russian Postgres Company --------------1509A57DCE8E829C22953273 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit

Hello, hackers!

We were testing how well some application works with PostgreSQL and stumbled upon an autovacuum behavior which I fail to understand.
Application in question have a habit to heavily use temporary tables in funny ways.
For example it creates A LOT of them.
Which is ok.
Funny part is that it never drops them. So when backend is finally terminated, it tries to drop them and fails with error:

FATAL:  out of shared memory
HINT:  You might need to increase max_locks_per_transaction

If I understand that rigth, we are trying to drop all these temp tables in one transaction and running out of locks to do so.
After that postgresql.log is flooded at the rate 1k/s with messages like that:

LOG:  autovacuum: found orphan temp table "pg_temp_15"."tt38147" in database "DB_TEST"

It produces a noticeable load on the system and it`s getting worst with every terminated backend or restart.
I did some RTFS and it appears that autovacuum has no intention of cleaning that orphan tables unless
it`s wraparound time:

src/backend/postmaster/autovacuum.c
             /* We just ignore it if the owning backend is still active */
 2037             if (backendID == MyBackendId || BackendIdGetProc(backendID) == NULL)
 2038             {
 2039                 /*
 2040                  * We found an orphan temp table (which was probably left
 2041                  * behind by a crashed backend).  If it's so old as to need
 2042                  * vacuum for wraparound, forcibly drop it.  Otherwise just
 2043                  * log a complaint.
 2044                  */
 2045                 if (wraparound)
 2046                 {
 2047                     ObjectAddress object;
 2048
 2049                     ereport(LOG,
 2050                             (errmsg("autovacuum: dropping orphan temp table \"%s\".\"%s\" in database \"%s\"",
 2051                                  get_namespace_name(classForm->relnamespace),
 2052                                     NameStr(classForm->relname),
 2053                                     get_database_name(MyDatabaseId))));
 2054                     object.classId = RelationRelationId;
 2055                     object.objectId = relid;
 2056                     object.objectSubId = 0;
 2057                     performDeletion(&object, DROP_CASCADE, PERFORM_DELETION_INTERNAL);
 2058                 }
 2059                 else
 2060                 {
 2061                     ereport(LOG,
 2062                             (errmsg("autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"",
 2063                                  get_namespace_name(classForm->relnamespace),
 2064                                     NameStr(classForm->relname),
 2065                                     get_database_name(MyDatabaseId))));
 2066                 }
 2067             }
 2068         }


What is more troubling is that pg_statistic is starting to bloat badly.

LOG:  automatic vacuum of table "DB_TEST.pg_catalog.pg_statistic": index scans: 0
        pages: 0 removed, 68225 remain, 0 skipped due to pins
        tuples: 0 removed, 2458382 remain, 2408081 are dead but not yet removable
        buffer usage: 146450 hits, 31 misses, 0 dirtied
        avg read rate: 0.010 MB/s, avg write rate: 0.000 MB/s
        system usage: CPU 3.27s/6.92u sec elapsed 23.87 sec

What is the purpose of keeping orphan tables around and not dropping them on the spot?


-- 
Grigory Smolkin
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
--------------1509A57DCE8E829C22953273--