Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i5wYX-0005C1-2C for pgsql-bugs@arkaria.postgresql.org; Thu, 05 Sep 2019 18:32:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1i5wYV-0002Tr-Bw for pgsql-bugs@arkaria.postgresql.org; Thu, 05 Sep 2019 18:32:27 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i5wYU-0002Th-Vu; Thu, 05 Sep 2019 18:32:27 +0000 Received: from smtp-fw-6001.amazon.com ([52.95.48.154]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.92) (envelope-from ) id 1i5wYO-0000qJ-5C; Thu, 05 Sep 2019 18:32:25 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1567708339; x=1599244339; h=subject:to:cc:references:from:message-id:date: mime-version:in-reply-to; bh=XLeAtVe4JlTJ7p9Y0a3eVfZLdVs39Ktntpwwwm81OU4=; b=d6fjw4Q+ybqTT5NM6YgOXbHm+7PVtot2X9vXqCosjVn3oVnAhoqnRdNB 4CZK7zw4etpJHqrUE/yadJB/18444WJg2QGbh8D7dGAxq4endwb6RuAw3 IxbQgynp5twb3lN/tjzJAHKbcgx5feEEJqXJ7fRvGXIx4z7p24eYeIoru s=; X-IronPort-AV: E=Sophos;i="5.64,470,1559520000"; d="scan'208,217";a="413793630" Received: from iad6-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-2a-53356bf6.us-west-2.amazon.com) ([10.124.125.6]) by smtp-border-fw-out-6001.iad6.amazon.com with ESMTP; 05 Sep 2019 18:32:16 +0000 Received: from EX13MTAUWA001.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan2.pdx.amazon.com [10.170.41.162]) by email-inbound-relay-2a-53356bf6.us-west-2.amazon.com (Postfix) with ESMTPS id 50121A1C90; Thu, 5 Sep 2019 18:32:16 +0000 (UTC) Received: from EX13D18UWA002.ant.amazon.com (10.43.160.199) by EX13MTAUWA001.ant.amazon.com (10.43.160.118) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Thu, 5 Sep 2019 18:32:16 +0000 Received: from 186590ce269b.ant.amazon.com (10.43.160.20) by EX13D18UWA002.ant.amazon.com (10.43.160.199) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Thu, 5 Sep 2019 18:32:15 +0000 Subject: Re: ERROR: multixact X from before cutoff Y found to be still running To: Thomas Munro CC: "pgsql-bugs@postgresql.org" , PostgreSQL-development , "Bossart, Nathan" , "Nasby, Jim" References: From: Jeremy Schneider Message-ID: <32134d69-1999-6518-e1d6-e268a24cb8aa@amazon.com> Date: Thu, 5 Sep 2019 11:32:15 -0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/alternative; boundary="------------C2857C0EA88A45C2A5D71DBF" Content-Language: en-US X-Originating-IP: [10.43.160.20] X-ClientProxiedBy: EX13D13UWA004.ant.amazon.com (10.43.160.251) To EX13D18UWA002.ant.amazon.com (10.43.160.199) Precedence: Bulk List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --------------C2857C0EA88A45C2A5D71DBF Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit On 9/4/19 21:01, Thomas Munro wrote: > I suppose this requires you to run out of member space (for example > many backends key sharing the same FK) or maybe just set > autovacuum_multixact_freeze_max_age quite low, and then prolong the > life of a multixact for longer. On this particular production system, autovacuum_multixact_freeze_max_age is the default value of 400 million and it is not overridden for any tables.  Looks to me like this was just workload driven.  There are a number of FKs and those seem to be a likely candidate to me. > Does the problem fix itself once you > close the transaction that's in the oldest multixact, ie holding back > GetOldestMultiXact() from advancing? The really interesting thing about this case is that the only long-running connection was the autovacuum that had been running since Sunday. While we were investigating yesterday, the autovacuum process died without advancing relfrozenxid (users configured this system with poor logging, so it's not known whether autovac terminated from error or from a user who logged on to the system).  As soon as the autovacuum process died, we stopped getting the "multixact X from before cutoff Y" errors. It really appears that it was the autovacuum process itself that was providing the oldest running multixact which caused errors on yesterday's attempts to vacuum other tables - even though I though vacuum processes were ignored by that code.  I'll have to take another look at some point. Vacuum cost parameters had been adjusted after Sunday, so the original autovacuum would have used default settings.  Naturally, a new autovacuum process started up right away.  This new process - definitely using adjusted cost parameters - completed the vacuum of the large table with 5 passes (index_vacuum_count) in a couple hours.  Maintenance work memory was already at the max; there were many hundreds of millions of dead tuples that still remained to be cleaned up. The size of the large table (heap only) was about 75% of the memory on the server, and the table had three indexes each about half the size of the table.  The storage was provisioned at just over 10k IOPS; at this rate you could read all three indexes from the storage one block at a time in about an hour.  (And Linux should be reading more than a block at a time.) It is not known whether the original autovacuum failed to completely vacuum the large table in 3 days because of cost settings alone or because there's another latent bug somewhere in the autovacuum code that put it into some kind of loop (but if autovac hit the error above then the PID would have terminated).  We didn't manage to get a pstack. > Since VACUUM errors out, we > don't corrupt data, right? Everyone else is still going to see the > multixact as running and do the right thing because vacuum never > manages to (bogusly) freeze the tuple. That's my take as well.  I don't think there's any data corruption risk here. If anyone else ever hits this in the future, I think it's safe to just kill the oldest open session. The error should go away and there shouldn't be any risk of damage to the database. > Both patches prevent mxactLimit from being newer than the oldest > running multixact. The v1 patch uses the most aggressive setting > possible: the oldest running multi; the v2 uses the least aggressive > of the 'safe' and oldest running multi. At first glance it seems like > the second one is better: it only does something different if we're in > the dangerous scenario you identified, but otherwise it sticks to the > safe limit, which generates less IO. Thanks for taking a look! -Jeremy -- Jeremy Schneider Database Engineer Amazon Web Services --------------C2857C0EA88A45C2A5D71DBF Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: 8bit
On 9/4/19 21:01, Thomas Munro wrote:
I suppose this requires you to run out of member space (for example
many backends key sharing the same FK) or maybe just set
autovacuum_multixact_freeze_max_age quite low, and then prolong the
life of a multixact for longer.
On this particular production system, autovacuum_multixact_freeze_max_age is the default value of 400 million and it is not overridden for any tables.  Looks to me like this was just workload driven.  There are a number of FKs and those seem to be a likely candidate to me.

Does the problem fix itself once you
close the transaction that's in the oldest multixact, ie holding back
GetOldestMultiXact() from advancing?  
The really interesting thing about this case is that the only long-running connection was the autovacuum that had been running since Sunday. While we were investigating yesterday, the autovacuum process died without advancing relfrozenxid (users configured this system with poor logging, so it's not known whether autovac terminated from error or from a user who logged on to the system).  As soon as the autovacuum process died, we stopped getting the "multixact X from before cutoff Y" errors.

It really appears that it was the autovacuum process itself that was providing the oldest running multixact which caused errors on yesterday's attempts to vacuum other tables - even though I though vacuum processes were ignored by that code.  I'll have to take another look at some point.

Vacuum cost parameters had been adjusted after Sunday, so the original autovacuum would have used default settings.  Naturally, a new autovacuum process started up right away.  This new process - definitely using adjusted cost parameters - completed the vacuum of the large table with 5 passes (index_vacuum_count) in a couple hours.  Maintenance work memory was already at the max; there were many hundreds of millions of dead tuples that still remained to be cleaned up.

The size of the large table (heap only) was about 75% of the memory on the server, and the table had three indexes each about half the size of the table.  The storage was provisioned at just over 10k IOPS; at this rate you could read all three indexes from the storage one block at a time in about an hour.  (And Linux should be reading more than a block at a time.)

It is not known whether the original autovacuum failed to completely vacuum the large table in 3 days because of cost settings alone or because there's another latent bug somewhere in the autovacuum code that put it into some kind of loop (but if autovac hit the error above then the PID would have terminated).  We didn't manage to get a pstack.

Since VACUUM errors out, we
don't corrupt data, right?  Everyone else is still going to see the
multixact as running and do the right thing because vacuum never
manages to (bogusly) freeze the tuple.
That's my take as well.  I don't think there's any data corruption risk here.

If anyone else ever hits this in the future, I think it's safe to just kill the oldest open session. The error should go away and there shouldn't be any risk of damage to the database.

Both patches prevent mxactLimit from being newer than the oldest
running multixact.  The v1 patch uses the most aggressive setting
possible: the oldest running multi; the v2 uses the least aggressive
of the 'safe' and oldest running multi.  At first glance it seems like
the second one is better: it only does something different if we're in
the dangerous scenario you identified, but otherwise it sticks to the
safe limit, which generates less IO.
Thanks for taking a look!

-Jeremy


-- 
Jeremy Schneider
Database Engineer
Amazon Web Services
--------------C2857C0EA88A45C2A5D71DBF--