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 1g9syQ-0000sy-C9 for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Oct 2018 14:26:59 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1g9syO-0008TC-9W for pgsql-hackers@arkaria.postgresql.org; Tue, 09 Oct 2018 14:26:56 +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 1g9syN-0008Sw-QK for pgsql-hackers@lists.postgresql.org; Tue, 09 Oct 2018 14:26:56 +0000 Received: from mail.postgrespro.ru ([93.174.131.138]) by makus.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1g9syJ-00070u-He for pgsql-hackers@postgresql.org; Tue, 09 Oct 2018 14:26:54 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.postgrespro.ru (Postfix) with ESMTP id DDEF621C2BF2; Tue, 9 Oct 2018 17:26:49 +0300 (MSK) X-Virus-Scanned: Debian amavisd-new at postgrespro.ru X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=x tagged_above=-99 required=4 WHITELISTED tests=[] autolearn=unavailable Received: from [192.168.27.200] (gw.postgrespro.ru [93.174.131.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) by mail.postgrespro.ru (Postfix) with ESMTPSA id 9215021C2BEA; Tue, 9 Oct 2018 17:26:49 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mail; t=1539095209; bh=mRTQGdtujFWjqeZNYS/ltBWNNE33rbEO2fnQe6NpqoQ=; h=Subject:To:Cc:References:From:Date:In-Reply-To; b=ddVOgCEAeDvJ0Cm+46SS/9EvnDm1GUV2LYHrVPzOX/0QokRsHn3NL8Y90Jj3V/uFT 5MCQ50XHnYw82tivT+VOTtpY3NvvDGeuzDVY1xHPR3dmasKDveTyuu8J1JalRnX3/M zHQkYsz1MEkxC66XbFLzEnpM1WBuWlb77kBZfpW8= Subject: Re: out-of-order XID insertion in KnownAssignedXids To: Michael Paquier , Andres Freund Cc: pgsql-hackers@lists.postgresql.org, PostgreSQL Hackers References: <0c96b653-4696-d4b4-6b5d-78143175d113@postgrespro.ru> <20181005080422.GA7863@paquier.xyz> <581a80f7-3992-f319-302d-7c9a384d64f7@postgrespro.ru> <2A819787-9E67-41EF-B89A-A906996924E5@anarazel.de> <20181008163049.nvaui5kjrsav2ojn@alap3.anarazel.de> <20181009055900.GH2137@paquier.xyz> <20181009075258.GI2137@paquier.xyz> From: Konstantin Knizhnik Message-ID: <1e1d56e2-b056-5fa1-bc89-a6bb3836a1c8@postgrespro.ru> Date: Tue, 9 Oct 2018 17:26:49 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: <20181009075258.GI2137@paquier.xyz> Content-Type: multipart/alternative; boundary="------------D800BFD1061A8DE9CFA5616C" Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------D800BFD1061A8DE9CFA5616C Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit On 09.10.2018 10:52, Michael Paquier wrote: > On Tue, Oct 09, 2018 at 02:59:00PM +0900, Michael Paquier wrote: >> +1. I am looking at how to make that possible. > And so... Going through a bit of investigation the problem is that each > 2PC transaction preparing finishes by putting the procarray in a state > where there are two entries referring to the same transaction running as > MarkAsPrepared adds an extra entry on the top of the one already > existing. This is expected though per the comments in > ProcArrayClearTransaction(), as it assumes that MyProc can be safely > cleaned and it assumes that there is a duplicated entry. Then, > GetRunningTransactionData() ignores the assumption that those duplicate > entries can exist, which makes the snapshot data taken as incorrect, > generating those incorrect XLOG_RUNNING_XACT records. > > The most simple fix I can think of first is to tweak the origin of the > problem in GetRunningTransactionData() so as those duplicate XIDs are > ignored if found as there has to be a state between the time > MarkAsPrepared() inserted the 2PC entry in the procarray and the time > ProcArrayClearTransaction() gets called. > -- > Michael Right now GetRunningTransactionData is used only once in Postgres code - in LogStandbySnapshot to log RUNNING_XACTS record. So if this situation is not changed, there will be no difference whether to perform sort and exclude duplicates in LogStandbySnapsho or GetRunningTransactionData. But GetRunningTransactionData may be used in some other cases... For example I have used it in my snapfs Postgres extensions (fast file-level snapshots) to check if there are no more active transactions in the system. In my case presence of duplicates is not important and ordering of XIDs is not needed. But performance of GetRunningTransactionData is also not critical. But I can suspect that there can be cases when it is critical and doing unneeded qsort is not desired. There may be thousands of active transactions and sorting their XIDs is notinstantaneous. Also please take in account that in most cases XIDs in RUNNINGS_XACTS record are not processed at all (only if we perform recovery from backup and do not reach consistent point yet). This is why this bug was not detected before. So I completely understand the argument that it is better to eliminate source of the problem (presence of duplicates in RUNNING_XACTS record) but not sure that in this particular case it is really the best solution. If presence of duplicates is considered to be acceptable for procarray, why we can not accept it for RUNNING_XACTS record? I am not insisting that skipping duplicates in ProcArrayApplyRecoveryInfo is the right place (but at least is seems to be the most efficient alternative). But I also do not fill that moving sort to GetRunningTransactionData and elimination of duplicates here (requires one more scan and copying of the whole array) is principally better... -- Konstantin Knizhnik Postgres Professional: http://www.postgrespro.com The Russian Postgres Company --------------D800BFD1061A8DE9CFA5616C Content-Type: text/html; charset=windows-1252 Content-Transfer-Encoding: 7bit

On 09.10.2018 10:52, Michael Paquier wrote:
On Tue, Oct 09, 2018 at 02:59:00PM +0900, Michael Paquier wrote:
+1.  I am looking at how to make that possible.
And so...  Going through a bit of investigation the problem is that each
2PC transaction preparing finishes by putting the procarray in a state
where there are two entries referring to the same transaction running as
MarkAsPrepared adds an extra entry on the top of the one already
existing.  This is expected though per the comments in
ProcArrayClearTransaction(), as it assumes that MyProc can be safely
cleaned and it assumes that there is a duplicated entry.  Then,
GetRunningTransactionData() ignores the assumption that those duplicate
entries can exist, which makes the snapshot data taken as incorrect,
generating those incorrect XLOG_RUNNING_XACT records.

The most simple fix I can think of first is to tweak the origin of the
problem in GetRunningTransactionData() so as those duplicate XIDs are
ignored if found as there has to be a state between the time
MarkAsPrepared() inserted the 2PC entry in the procarray and the time
ProcArrayClearTransaction() gets called.
--
Michael

Right now GetRunningTransactionData is used only once in Postgres code - in LogStandbySnapshot to log RUNNING_XACTS record.
So if this situation is not changed, there will be no difference whether to perform sort and exclude duplicates in LogStandbySnapsho
or GetRunningTransactionData.

But GetRunningTransactionData may be used in some other cases... For example I have used it in my snapfs Postgres extensions (fast file-level snapshots)
to check if there are no more active transactions in the system. In my case presence of duplicates is not important and ordering of XIDs is not needed.
But performance of GetRunningTransactionData is also not critical. But I can suspect that there can be cases when it is critical and doing unneeded qsort is not desired.
There may be thousands of active transactions and sorting their XIDs is not instantaneous.

Also please take in account that in most cases XIDs in RUNNINGS_XACTS record are not processed at all (only if we perform recovery from backup and do not reach consistent point yet). This is why this bug was not detected before.

So I completely understand the argument that it is better to eliminate source of the problem (presence of duplicates in RUNNING_XACTS record)
but not sure that in this particular case it is really the best solution. If presence of duplicates is considered to be acceptable for procarray, why we
can not accept it for RUNNING_XACTS record?
I am not insisting that skipping duplicates in ProcArrayApplyRecoveryInfo is the right place (but at least is seems to be the most efficient alternative). But I also do not fill that moving sort to GetRunningTransactionData and elimination of duplicates here (requires one more scan and copying of the whole array) is principally better...


-- 
Konstantin Knizhnik
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company 
--------------D800BFD1061A8DE9CFA5616C--