Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1WsxIo-0001NU-MD for pgsql-bugs@arkaria.postgresql.org; Fri, 06 Jun 2014 16:47:38 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.80) (envelope-from ) id 1WsxIo-00058D-4w for pgsql-bugs@arkaria.postgresql.org; Fri, 06 Jun 2014 16:47:38 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1WsxIn-000586-2S for pgsql-bugs@postgresql.org; Fri, 06 Jun 2014 16:47:37 +0000 Received: from smtprelay0143.b.hostedemail.com ([64.98.42.143] helo=smtprelay.b.hostedemail.com) by magus.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1WsxIh-0008IP-RH for pgsql-bugs@postgresql.org; Fri, 06 Jun 2014 16:47:35 +0000 Received: from filter.hostedemail.com (b-bigip1 [10.5.19.254]) by smtprelay06.b.hostedemail.com (Postfix) with ESMTP id 735A18D015; Fri, 6 Jun 2014 16:47:29 +0000 (UTC) X-Session-Marker: 616C76686572726540616C76682E6E6F2D69702E6F7267 X-Spam-Summary: 40, 2.5, 0, , d41d8cd98f00b204, alvherre@alvh.no-ip.org, :::, RULES_HIT:41:355:379:599:871:967:973:988:989:1260:1311:1312:1313:1314:1345:1359:1437:1515:1516:1518:1519:1535:1541:1575:1594:1595:1596:1711:1730:1747:1764:1777:1792:2198:2199:2393:2525:2560:2563:2682:2685:2859:2895:2901:2933:2937:2939:2942:2945:2947:2951:2954:3022:3138:3139:3140:3141:3142:3353:3865:3866:3867:3868:3870:3871:3872:3874:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4117:4321:4605:4659:5007:6119:6261:6748:6996:6997:7281:7903:8957:9025:9121:10011:10400:10848:11026:11232:11256:11257:11473:11604:11658:11914:12438:12517:12519:12555:12663:12740:13161:13229:13255:13894:13895, 0, RBL:none, CacheIP:none, Bayesian:0.5, 0.5, 0.5, Netcheck:none, DomainCache:0, MSF:not bulk, SPF:fn, MSBL:0, DNSBL:none, Custom_rules:0:2:0 X-HE-Tag: cave62_2428d47f43f07 X-Filterd-Recvd-Size: 6302 Received: from eldon.alvh.no-ip.org (pc-65-79-161-190.cm.vtr.net [190.161.79.65]) (Authenticated sender: alvherre@alvh.no-ip.org) by omf07.b.hostedemail.com (Postfix) with ESMTPA; Fri, 6 Jun 2014 16:47:28 +0000 (UTC) Received: by eldon.alvh.no-ip.org (Postfix, from userid 1000) id 492EC1FC9; Fri, 6 Jun 2014 12:47:27 -0400 (CLT) Date: Fri, 6 Jun 2014 12:47:27 -0400 From: Alvaro Herrera To: Serge Negodyuck Cc: pgsql-bugs@postgresql.org Subject: Re: BUG #8673: Could not open file "pg_multixact/members/xxxx" on slave during hot_standby Message-ID: <20140606164727.GU5146@eldon.alvh.no-ip.org> References: <20131209142525.GA1123@awork2.anarazel.de> <20131209150345.GB1123@awork2.anarazel.de> <20131209182701.GD9519@awork2.anarazel.de> <20140103014616.GB7035@eldon.alvh.no-ip.org> <20140606013943.GT5146@eldon.alvh.no-ip.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="9Ek0hoCL9XbhcSqy" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20140606013943.GT5146@eldon.alvh.no-ip.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Pg-Spam-Score: -1.9 (-) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-bugs Precedence: bulk Sender: pgsql-bugs-owner@postgresql.org --9Ek0hoCL9XbhcSqy Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit 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 --9Ek0hoCL9XbhcSqy Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="multixact-offset-wraparound-2.patch" *** 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 --9Ek0hoCL9XbhcSqy Content-Type: text/plain Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs --9Ek0hoCL9XbhcSqy--