From: Alvaro Herrera <alvherre@2ndquadrant.com>
To: Serge Negodyuck <petr@petrovich.kiev.ua>
Cc: pgsql-bugs@postgresql.org
Subject: Re: BUG #8673: Could not open file "pg_multixact/members/xxxx" on slave during hot_standby
Date: Fri, 6 Jun 2014 12:47:27 -0400
Message-ID: <20140606164727.GU5146@eldon.alvh.no-ip.org> (raw)
In-Reply-To: <20140606013943.GT5146@eldon.alvh.no-ip.org>
References: <E1Vq1BO-00064N-Qn@wrigleys.postgresql.org>
<20131209142525.GA1123@awork2.anarazel.de>
<CABKyZDFWn+ty_m88sq2j5UThowb2Qwd0125BNx_19va2Fn57dQ@mail.gmail.com>
<20131209150345.GB1123@awork2.anarazel.de>
<CABKyZDFRtDzcY1=sEznC2ivmcM5p1yPQvC8qLL8XLviNF2kp7A@mail.gmail.com>
<20131209182701.GD9519@awork2.anarazel.de>
<20140103014616.GB7035@eldon.alvh.no-ip.org>
<CABKyZDEV49nUYJej9Hv-hPUS=VUmMt1LmVV=YW=fV5X8nKtdtw@mail.gmail.com>
<20140606013943.GT5146@eldon.alvh.no-ip.org>
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-bugs>
Alvaro Herrera wrote:
> Serge Negodyuck wrote:
>
> > 2014-06-02 08:20:55 EEST 172.18.10.4 db PANIC: could not access status of
> > transaction 2080547
> > 2014-06-02 08:20:55 EEST 172.18.10.4 db DETAIL: Could not open file
> > "pg_multixact/members/14078": No such file or directory.
> > 2014-06-02 08:20:55 EEST 172.18.10.4 db CONTEXT: SQL statement " UPDATE
> > ....."
>
> So as it turns out, this was caused because the arithmetic to handle the
> wraparound case neglected to handle multixacts with more members than
> the number that fit in the last page(s) of the last segment, leading to
> a number of pages in the 14078 segment (or whatever the last segment is
> for a given BLCKSZ) to fail to be initialized. This patch is a rework
> of that arithmetic, although it seems little bit too obscure.
After some simplification I think it should be clearer. Thanks Andres
for commenting offlist.
There is a different way to compute the "difference" proposed by Andres,
without using if/else; the idea is to cast the values to int64 and then
clamp. It would be something like
uint64 diff64;
diff64 = Min((uint64) offset + nmembers,
(uint64) offset + MULTIXACT_MEMBERS_PER_PAGE);
difference = (uint32) Min(diff64, MaxMultiXactOffset);
(There are other ways to formulate this, of course, but this seems to me
to be the most readable one). I am undecided between this and the one I
propose in the patch, so I've stuck with the patch.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugsAttachments:multixact-offset-wraparound-2.patch (text/x-diff, 2.8K) download
*** a/src/backend/access/transam/multixact.c
--- b/src/backend/access/transam/multixact.c
***************
*** 133,138 ****
--- 133,151 ----
#define MULTIXACT_MEMBERS_PER_PAGE \
(MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
+ /*+ * Because the number of items per page is not a divisor of the last item+ * number (member 0xFFFFFFFF), the last segment does not use the maximum number+ * of pages, and moreover the last used page therein does not use the same+ * number of items as previous pages. (Another way to say it is that the+ * 0xFFFFFFFF member is somewhere in the middle of the last page, so the page+ * has some empty space after that item.)+ *+ * This constant is the number of members in the last page of the last segment.+ */+ #define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE \+ ((uint32) ((0xFFFFFFFF % MULTIXACT_MEMBERS_PER_PAGE) + 1))+
/* page in which a member is to be found */
#define MXOffsetToMemberPage(xid) ((xid) / (TransactionId) MULTIXACT_MEMBERS_PER_PAGE)
***************
*** 2278,2283 **** ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
--- 2291,2297 ----
{
int flagsoff;
int flagsbit;
+ uint32 difference;
/*
* Only zero when at first entry of a page.
***************
*** 2302,2322 **** ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
* Advance to next page, taking care to properly handle the wraparound
* case. OK if nmembers goes negative.
*/
- if ((unsigned int) (offset + nmembers) < offset)- {- uint32 difference = offset + MULTIXACT_MEMBERS_PER_PAGE;
! nmembers -= (unsigned int) (MULTIXACT_MEMBERS_PER_PAGE - difference);
! offset = 0;
}
else
- {- int difference;-
difference = MULTIXACT_MEMBERS_PER_PAGE - offset % MULTIXACT_MEMBERS_PER_PAGE;
! nmembers -= difference;
! offset += difference;
! }
}
}
--- 2316,2335 ----
* Advance to next page, taking care to properly handle the wraparound
* case. OK if nmembers goes negative.
*/
! if (offset + MAX_MEMBERS_IN_LAST_MEMBERS_PAGE < offset)
! {
! /*
! * This is the last page of the last segment; we can compute the
! * number of items in it without modulo arithmetic.
! */
! difference = MaxMultiXactOffset - offset + 1;
}
else
difference = MULTIXACT_MEMBERS_PER_PAGE - offset % MULTIXACT_MEMBERS_PER_PAGE;
!
! nmembers -= difference;
! offset += difference;
}
}
*** a/src/include/access/multixact.h
--- b/src/include/access/multixact.h
***************
*** 25,30 ****
--- 25,32 ----
#define MultiXactIdIsValid(multi) ((multi) != InvalidMultiXactId)
+ #define MaxMultiXactOffset ((MultiXactOffset) 0xFFFFFFFF)+
/* Number of SLRU buffers to use for multixact */
#define NUM_MXACTOFFSET_BUFFERS 8
#define NUM_MXACTMEMBER_BUFFERS 16
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: alvherre@2ndquadrant.com, petr@petrovich.kiev.ua, pgsql-bugs@postgresql.org
Subject: Re: BUG #8673: Could not open file "pg_multixact/members/xxxx" on slave during hot_standby
In-Reply-To: <20140606164727.GU5146@eldon.alvh.no-ip.org>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox