Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dwO36-0000zo-KA for pgsql-hackers@arkaria.postgresql.org; Mon, 25 Sep 2017 07:43:28 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1dwO36-0002ho-5W for pgsql-hackers@arkaria.postgresql.org; Mon, 25 Sep 2017 07:43:28 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1dwO35-0002he-6p for pgsql-hackers@postgresql.org; Mon, 25 Sep 2017 07:43:27 +0000 Received: from tama50.ecl.ntt.co.jp ([129.60.39.147]) by makus.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dwO31-0000oX-Oy for pgsql-hackers@postgresql.org; Mon, 25 Sep 2017 07:43:26 +0000 Received: from vc1.ecl.ntt.co.jp (vc1.ecl.ntt.co.jp [129.60.86.153]) by tama50.ecl.ntt.co.jp (8.13.8/8.13.8) with ESMTP id v8P7hLbR004444; Mon, 25 Sep 2017 16:43:21 +0900 Received: from vc1.ecl.ntt.co.jp (localhost [127.0.0.1]) by vc1.ecl.ntt.co.jp (Postfix) with ESMTP id 8666E5F65A; Mon, 25 Sep 2017 16:43:21 +0900 (JST) Received: from jcms-pop21.ecl.ntt.co.jp (jcms-pop21.ecl.ntt.co.jp [129.60.87.134]) by vc1.ecl.ntt.co.jp (Postfix) with ESMTP id 7A3C85F623; Mon, 25 Sep 2017 16:43:21 +0900 (JST) Received: from [127.0.0.1] (unknown [129.60.241.61]) by jcms-pop21.ecl.ntt.co.jp (Postfix) with ESMTPSA id 75AB9400C9F; Mon, 25 Sep 2017 16:43:21 +0900 (JST) Subject: Re: Shaky coding for vacuuming partitioned relations References: <25023.1506107590@sss.pgh.pa.us> From: Amit Langote Message-ID: Date: Mon, 25 Sep 2017 16:42:22 +0900 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit To: Michael Paquier , Tom Lane Cc: PostgreSQL mailing lists X-TM-AS-MML: disable 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 On 2017/09/25 12:10, Michael Paquier wrote: > On Sat, Sep 23, 2017 at 4:13 AM, Tom Lane wrote: >> Somebody inserted this into vacuum.c's get_rel_oids(): >> >> tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); >> if (!HeapTupleIsValid(tuple)) >> elog(ERROR, "cache lookup failed for relation %u", relid); >> >> apparently without having read the very verbose comment two lines above, >> which points out that we're not taking any lock on the target relation. >> So, if that relation is concurrently being dropped, you're likely to >> get "cache lookup failed for relation NNNN" rather than anything more >> user-friendly. > > This has been overlooked during the lookups of 3c3bb99, and by > multiple people including me. elog() should never be things users can > face, as well as cache lookups. Agreed, that was an oversight. >> A minimum-change fix would be to replace the elog() with an ereport >> that produces the same "relation does not exist" error you'd have >> gotten from RangeVarGetRelid, had the concurrent DROP TABLE committed >> a few microseconds earlier. But that feels like its's band-aiding >> around the problem. > > Yeah, that's not right. This is a cache lookup error at the end. Also agreed that fixing the locking here would be a better solution. >> What I'm wondering about is changing the RangeVarGetRelid call to take >> ShareUpdateExclusiveLock rather than no lock. That would protect the >> syscache lookup, and it would also make the find_all_inheritors call >> a lot more meaningful. >> >> If we're doing a VACUUM, the ShareUpdateExclusiveLock would be dropped >> as soon as we close the caller's transaction, and then we'd acquire >> the same or stronger lock inside vacuum_rel(). So that seems fine. >> If we're doing an ANALYZE, then the lock would continue to be held >> and analyze_rel would merely be acquiring it an extra time, so we'd >> actually be removing a race-condition failure scenario for ANALYZE. >> This would mean a few more cycles in lock management, but since this >> only applies to a manual VACUUM or ANALYZE that specifies a table >> name, I'm not too concerned about that. > > I think that I am +1 on that. Testing such a thing I am not seeing > anything wrong either. The call to find_all_inheritors should also use > ShareUpdateExclusiveLock, and the lock on top of RangeVarGetRelid() > needs to be reworked. > > Attached is a proposal of patch. Hmm, I'm not sure if we need to lock the partitions, too. Locks taken by find_all_inheritors() will be gone once the already-running transaction is ended by the caller (vacuum()). get_rel_oids() should just lock the table mentioned in the command (the parent table), so that find_all_inheritors() returns the correct partition list, as Tom perhaps alluded to when he said "it would also make the find_all_inheritors call a lot more meaningful.", but... When vacuum() iterates that list and calls vacuum_rel() for each relation in the list, it might be the case that a relation in that list is no longer a partition of the parent. So, one might say that it would get vacuumed unnecessarily. Perhaps that's fine? >> Thoughts? > > As long as I don't forget... Another thing currently on HEAD and > REL_10_STABLE is that OIDs of partitioned tables are used, but the > RangeVar of the parent is used for error reports. This leads to > incorrect reports if a partition gets away in the middle of autovacuum > as only information about the parent is reported to the user. Oh, you're right. The original RangeVar (corresponding to the table mentioned in the command) refers to the parent table. > I am not > saying that this needs to be fixed in REL_10_STABLE at this stage > though as this would require some refactoring similar to what the > patch adding support for VACUUM with multiple relations does. I think it would be better to fix that independently somehow. VACUUM on partitioned tables is handled by calling vacuum_rel() on individual partitions. It would be nice if vacuum_rel() didn't have to refer to the RangeVar. Could we not use get_rel_name(relid) in place of relation->relname? I haven't seen the other patch yet though, so maybe I'm missing something. Thanks, Amit -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers