Received: from malur.postgresql.org ([2a02:16a8:dc51::56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fimTO-0005Ub-Ia for pgsql-hackers@arkaria.postgresql.org; Thu, 26 Jul 2018 20:02:54 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1fimTL-0003Fb-NE for pgsql-hackers@arkaria.postgresql.org; Thu, 26 Jul 2018 20:02:51 +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.89) (envelope-from ) id 1fimTL-0003FU-CM for pgsql-hackers@lists.postgresql.org; Thu, 26 Jul 2018 20:02:51 +0000 Received: from out1-smtp.messagingengine.com ([66.111.4.25]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fimTE-0000L2-IB for pgsql-hackers@postgresql.org; Thu, 26 Jul 2018 20:02:50 +0000 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 4EA2620D92; Thu, 26 Jul 2018 16:02:43 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute5.internal (MEProxy); Thu, 26 Jul 2018 16:02:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anarazel.de; h= cc:content-type:date:from:in-reply-to:message-id:mime-version :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=+EWsI32/Eq+bPhM3FqGxtnJxq/xK4FFipOIZaslclsk=; b=h6vpTnlP cosCZg1OtRVJj1CoIMzu4pPP4pThoa65k8OcN0zGjXB1+tQ7YRMlr4lgJYPaHgz8 SWYX5iK6sbKiZzRQEgzhsp13j+9pScY6VJ2x43aw4r4gRRPs8YGBpIrabEjhv1NX fltVe1qsjvkLk+zGJM4OZtyhWW7ZbZqLRz3O5q1cjX7DLSMTp8Xsodj8viN5QCgi OWRjQAdlhJvWNo5qs7knGC1czmfg/OgcPzum6f3G6VkI+MABOp9Vafaqk6ALKMpa iX6GTT6Pu81UdcDPwyj/DFc5r8G0uZlsm+PpizYWKa4Cfi4mjy3DegyLkh8UHnwT LTBPM2aIc8ZRkw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; bh=+EWsI32/Eq+bPhM3FqGxtnJxq/xK4 FFipOIZaslclsk=; b=sroPK3BKzzjlRrR9X/sCMIOUUVSJxpWTBqY8N9S3UMI71 JpSBvN95dpWVhZuhWp58mdrCicU77fx6A9xpkd+amYB+IlByR2/8EPhjGeVNLqKR IQdS3SrBSReOiByT51nlYTtzKQLm2pdFrdSMLE6krOpm/fSdmm1w3iGaCDqRDb6k CLgW9pUXKf8LHTbgitJo1TSeN/HJxCeVE42iO3PI0gj0VJlImfscaDtt4dlQjmSF nNMq2Ma+eZo4oL1ixCe76LLQrTQipB/3KyrYY06it3u6tZ9v3qyn3Buo55RH4jrI AjW+1E4ItyWhWTjWTS81OHZRCDK7huFQtsEJkWfvw== X-ME-Proxy: X-ME-Sender: Received: from intern.anarazel.de (96-86-174-91-static.hfc.comcastbusiness.net [96.86.174.91]) by mail.messagingengine.com (Postfix) with ESMTPA id 7E4D1E4636; Thu, 26 Jul 2018 16:02:42 -0400 (EDT) Date: Thu, 26 Jul 2018 13:02:41 -0700 From: Andres Freund To: Nikhil Sontakke Cc: Robert Haas , Tomas Vondra , David Steele , Andrew Dunstan , Simon Riggs , Craig Ringer , Peter Eisentraut , Petr Jelinek , Sokolov Yura , Stas Kelvich , Dmitry Dolgov <9erthalion6@gmail.com>, Tom Lane , Masahiko Sawada , PostgreSQL Hackers Subject: Re: [HACKERS] logical decoding of two-phase transactions Message-ID: <20180726200241.aje4dv4jsv25v4k2@alap3.anarazel.de> References: <20180719194208.j5m7qhdmqp46d6yg@alap3.anarazel.de> <20180719223500.lclj45aiojikwnwm@alap3.anarazel.de> <20180720145836.gxwhbftuoyx5h4gc@alap3.anarazel.de> <20180723135009.w25re6qxbb7njrbd@alap3.anarazel.de> <20180723141435.ercxxh3bj2uc2mjm@alap3.anarazel.de> <3B37B16B-A473-4352-ABCF-F23AE314D4F7@2ndquadrant.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On 2018-07-26 20:24:00 +0530, Nikhil Sontakke wrote: > Hi, > > >> I think we even can just do something like a global > >> TransactionId check_if_transaction_is_alive = InvalidTransactionId; > >> and just set it up during decoding. And then just check it whenever it's > >> not set tot InvalidTransactionId. > >> > >> > > > > Ok. I will work on something along these lines and re-submit the set of patches. > PFA, latest patchset, which completely removes the earlier > LogicalLock/LogicalUnLock implementation using groupDecode stuff and > uses the newly suggested approach of checking the currently decoded > XID for abort in systable_* API functions. Much simpler to code and > easier to test as well. So, leaving the fact that it might not actually be correct aside ;), you seem to be ok with the approach? > Out of the patchset, the specific patch which focuses on the above > systable_* API based XID checking implementation is part of > 0003-Gracefully-handle-concurrent-aborts-of-uncommitted-t.patch. So, > it might help to take a look at this patch first for any additional > feedback on this approach. K. > There's an additional test case in > 0005-Additional-test-case-to-demonstrate-decoding-rollbac.patch which > uses a sleep in the "change" plugin API to allow a concurrent rollback > on the 2PC being currently decoded. Andres generally doesn't like this > approach :-), but there are no timing/interlocking issues now, and the > sleep just helps us do a concurrent rollback, so it might be ok now, > all things considered. Anyways, it's an additional patch for now. Yea, I still don't think it's ok. The tests won't be reliable. There's ways to make this reliable, e.g. by forcing a lock to be acquired that's externally held or such. Might even be doable just with a weird custom datatype. > From 75edeb440794fff7de48082dafdecb065940bee5 Mon Sep 17 00:00:00 2001 > From: Nikhil Sontakke > Date: Thu, 26 Jul 2018 18:45:26 +0530 > Subject: [PATCH 3/5] Gracefully handle concurrent aborts of uncommitted > transactions that are being decoded alongside. > > When a transaction aborts, it's changes are considered unnecessary for > other transactions. That means the changes may be either cleaned up by > vacuum or removed from HOT chains (thus made inaccessible through > indexes), and there may be other such consequences. > > When decoding committed transactions this is not an issue, and we > never decode transactions that abort before the decoding starts. > > But for in-progress transactions - for example when decoding prepared > transactions on PREPARE (and not COMMIT PREPARED as before), this > may cause failures when the output plugin consults catalogs (both > system and user-defined). > > We handle such failures by returning ERRCODE_TRANSACTION_ROLLBACK > sqlerrcode from system table scan APIs to the backend decoding a > specific uncommitted transaction. The decoding logic on the receipt > of such an sqlerrcode aborts the ongoing decoding and returns > gracefully. > --- > src/backend/access/index/genam.c | 31 +++++++++++++++++++++++++ > src/backend/replication/logical/reorderbuffer.c | 30 ++++++++++++++++++++---- > src/backend/utils/time/snapmgr.c | 25 ++++++++++++++++++-- > src/include/utils/snapmgr.h | 4 +++- > 4 files changed, 82 insertions(+), 8 deletions(-) > > diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c > index 9d08775687..67c5810bf7 100644 > --- a/src/backend/access/index/genam.c > +++ b/src/backend/access/index/genam.c > @@ -423,6 +423,16 @@ systable_getnext(SysScanDesc sysscan) > else > htup = heap_getnext(sysscan->scan, ForwardScanDirection); > > + /* > + * If CheckXidAlive is valid, then we check if it aborted. If it did, we > + * error out > + */ > + if (TransactionIdIsValid(CheckXidAlive) && > + TransactionIdDidAbort(CheckXidAlive)) > + ereport(ERROR, > + (errcode(ERRCODE_TRANSACTION_ROLLBACK), > + errmsg("transaction aborted during system catalog scan"))); > + > return htup; > } Don't we have to check TransactionIdIsInProgress() first? C.f. header comments in tqual.c. Note this is also not guaranteed to be correct after a crash (where no clog entry will exist for an aborted xact), but we probably shouldn't get here in that case - but better be safe. I suspect it'd be better reformulated as TransactionIdIsValid(CheckXidAlive) && !TransactionIdIsInProgress(CheckXidAlive) && !TransactionIdDidCommit(CheckXidAlive) What do you think? I think it'd also be good to add assertions to codepaths not going through systable_* asserting that !TransactionIdIsValid(CheckXidAlive). Alternatively we could add an if (unlikely(TransactionIdIsValid(CheckXidAlive)) && ...) branch to those too. > From 80fc576bda483798919653991bef6dc198625d90 Mon Sep 17 00:00:00 2001 > From: Nikhil Sontakke > Date: Wed, 13 Jun 2018 16:31:15 +0530 > Subject: [PATCH 4/5] Teach test_decoding plugin to work with 2PC > > Includes a new option "enable_twophase". Depending on this options > value, PREPARE TRANSACTION will either be decoded or treated as > a single phase commit later. FWIW, I don't think I'm ok with doing this on a per-plugin-option basis. I think this is something that should be known to the outside of the plugin. More similar to how binary / non-binary support works. Should also be able to inquire the output plugin whether it's supported (cf previous similarity). > From 682b0de2827d1f55c4e471c3129eb687ae0825a5 Mon Sep 17 00:00:00 2001 > From: Nikhil Sontakke > Date: Wed, 13 Jun 2018 16:32:16 +0530 > Subject: [PATCH 5/5] Additional test case to demonstrate decoding/rollback > interlocking > > Introduce a decode-delay parameter in the test_decoding plugin. Based > on the value provided in the plugin, sleep for those many seconds while > inside the "decode change" plugin call. A concurrent rollback is fired > off which aborts that transaction in the meanwhile. A subsequent > systable access will error out causing the logical decoding to abort. Yea, I'm *definitely* still not on board with this. This'll just lead to a fragile or extremely slow test. Greetings, Andres Freund