Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rD8p2-0013Rd-9n for pgsql-bugs@arkaria.postgresql.org; Tue, 12 Dec 2023 19:53:41 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rD8oz-007ovD-VE for pgsql-bugs@arkaria.postgresql.org; Tue, 12 Dec 2023 19:53:37 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rD8oy-007ov5-QG for pgsql-bugs@lists.postgresql.org; Tue, 12 Dec 2023 19:53:37 +0000 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rD8op-00Bffp-Vq for pgsql-bugs@lists.postgresql.org; Tue, 12 Dec 2023 19:53:35 +0000 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.west.internal (Postfix) with ESMTP id 53DC23200A93; Tue, 12 Dec 2023 14:53:23 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Tue, 12 Dec 2023 14:53:23 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1702410802; x= 1702497202; bh=jAUkTAS2QLgJyMsJnBv6yPO4P+zJw2Q1jdile/DmU2g=; b=f XFK79TJtmPETM4/2z4Rzmhvk1pOOD2HuHrD7BJOZHVvtpyn72vSxaVM9mz0urRGZ V6cHiPAcmCKgYPt9f3ErDRNO0l7K2ZiZSCMJiVMYKFzpRtlV6X3q5oWpO982Slrk oKsF4U18gUytHNV32f1c3J1pmOgW0qKdFFfDvc/GrgGcCstXEwbqayOMRadXtsXM BANn6p4eKjYVnSziwq1iDXelJT/eRPk9pO1utUN1cZbcbGGuVcwCrYraFcky30b9 ZMDtQTvfa4TVapy/CJorPqm68flPe0OMaRGuxz13NJP4kxY5VAHhsSsuqxcD10Sp +OPEozsQGdbpqec39DiLw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrudelgedguddvjecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpeffhffvvefukfggtggugfgjsehtkeertddttdejnecuhfhrohhmpeetlhhv rghrohcujfgvrhhrvghrrgcuoegrlhhvhhgvrhhrvgesrghlvhhhrdhnohdqihhprdhorh hgqeenucggtffrrghtthgvrhhnpedvkedtffduffdtffffheffhfejjefhgfeiueeukeej keffgfdufffhudffffeuveenucffohhmrghinhepvghnthgvrhhprhhishgvuggsrdgtoh hmnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghl vhhhvghrrhgvsegrlhhvhhdrnhhoqdhiphdrohhrgh X-ME-Proxy: Feedback-ID: ia2694551:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 12 Dec 2023 14:53:21 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alvh.no-ip.org; s=schmee; t=1702401104; bh=K9F+qA3hzvr3hRump/pDRWKrlzdJ5DP0UYnSSWTS2+Q=; h=Date:From:To:Cc:Subject:In-Reply-To:From; b=k3RWHSfEjGmVlT8ACXIzZAUelfNleHwsRQ/FOk3mf8RbfXhwG8BpumWCvJ/jl4FHh CHJ4YL6cETPJl7rxSs8WBSw449+IQq2xNWU2I3RbemZsFeZkqkzEGTjM7NC65G3Gte x+YxxtBbwqK6uyS3adV7GUSyoVm1EeCjJM/QSOQgro/4AMarKKafjFcHjQHgrVNFX3 1YXaOPKfjm5gdUa5Y6U1lt5/MCFAvFSvAFKzsSA/AQG7OR7ViIyEvgUqxHRfuCsdaZ hsTPjHQYDVeSuWhSrP9nSFqLxDwAsKbbGRPZXdwBZne/YYgi56NOCrfs+8+ez3EFcW Gi4PSWBowUGKg== Received: by schmee.alvh.no-ip.org (Postfix, from userid 1000) id 63E363B5; Tue, 12 Dec 2023 18:11:44 +0100 (CET) Date: Tue, 12 Dec 2023 18:11:44 +0100 From: Alvaro Herrera To: Michael Paquier Cc: Kyotaro Horiguchi , feichanghong@qq.com, pgsql-bugs@lists.postgresql.org Subject: Re: BUG #18241: PushTransaction may cause Standby to execute ItemIdMarkDead Message-ID: <202312121711.tzjyb5yeb3fa@alvherre.pgsql> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 2023-Dec-12, Michael Paquier wrote: > An issue if that this could cause problems if you do catalog > scans, which may explain a few bugs I recall seeing over the years, > even if these did not directly mention the use of ssavepoints. I'd > need to double-check the archives. If going through a driver layer > like the ODBC driver that enforces savepoints for each query, that > would be bad. What a horrible bug. Thanks for pushing the fix. It looks OK to me: nowhere else do we create a TransactionStateData that would need the initialization. I wonder if this can cause data corruption, if you happen to have a broken standby that improperly kills some index entry and is later promoted. Maybe this bug explains these mysterious cases where an index seems to lack a pointer to some heap tuple for no known reason -- especially notorious when you try to REINDEX a unique index and that turns out not to work due to duplicates. I would be happier if the order of initialization of the struct member followed the order to the struct, with comments to note the missing members. That might make it more visible to future patches that would add more members. Something like this: diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 8442c5e6a7..b5874df821 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -5291,17 +5291,25 @@ PushTransaction(void) */ s->fullTransactionId = InvalidFullTransactionId; /* until assigned */ s->subTransactionId = currentSubTransactionId; - s->parent = p; - s->nestingLevel = p->nestingLevel + 1; - s->gucNestLevel = NewGUCNestLevel(); + /* s->name = NULL; */ s->savepointLevel = p->savepointLevel; s->state = TRANS_DEFAULT; s->blockState = TBLOCK_SUBBEGIN; + s->nestingLevel = p->nestingLevel + 1; + s->gucNestLevel = NewGUCNestLevel(); + /* s->curTransactionContext = NULL; */ + /* s->curTransactionOwner = NULL */ + /* s->childXids = NULL; */ + /* s->nChildXids = 0; */ + /* s->maxChildXids = 0; */ GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext); s->prevXactReadOnly = XactReadOnly; s->startedInRecovery = p->startedInRecovery; + /* s->didLogXid = false; */ s->parallelModeLevel = 0; + /* s->chain = false; */ s->topXidLogged = false; + s->parent = p; CurrentTransactionState = s; Also, the way this function checks for overflow is strange. Why increment then check, leading to a forced free and decrement, instead of just testing and throwing error right away? It's less code: diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 8442c5e6a7..fac9141b16 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -5272,18 +5272,14 @@ PushTransaction(void) MemoryContextAllocZero(TopTransactionContext, sizeof(TransactionStateData)); - /* - * Assign a subtransaction ID, watching out for counter wraparound. - */ - currentSubTransactionId += 1; - if (currentSubTransactionId == InvalidSubTransactionId) - { - currentSubTransactionId -= 1; - pfree(s); + /* Check for overflow before incrementing the counter */ + if (currentSubTransactionId + 1 == InvalidSubTransactionId) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot have more than 2^32-1 subtransactions in a transaction"))); - } + + /* Now we can increment it without fear */ + currentSubTransactionId += 1; /* * We can now stack a minimally valid subtransaction without fear of -- Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/ "El que vive para el futuro es un iluso, y el que vive para el pasado, un imbécil" (Luis Adler, "Los tripulantes de la noche")