From b264bfe61b315a5f65d72b9550592cc9f73bf0a8 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Tue, 31 Dec 2013 00:42:11 -0300 Subject: [PATCH 1/3] pg_burn_multixact utility Andres Freund, minor tweaks by me (And then updated by Jeff to apply to pageinspect 1.2) diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c new file mode 100644 index dedc8fe..7903b35 *** a/contrib/pageinspect/heapfuncs.c --- b/contrib/pageinspect/heapfuncs.c *************** *** 29,34 **** --- 29,36 ---- #include "funcapi.h" #include "utils/builtins.h" #include "miscadmin.h" + #include "access/multixact.h" + #include "access/transam.h" /* *************** heap_page_items(PG_FUNCTION_ARGS) *** 222,224 **** --- 224,266 ---- else SRF_RETURN_DONE(fctx); } + + extern Datum + pg_burn_multixact(PG_FUNCTION_ARGS); + PG_FUNCTION_INFO_V1(pg_burn_multixact); + + Datum + pg_burn_multixact(PG_FUNCTION_ARGS) + { + int rep = PG_GETARG_INT32(0); + int size = PG_GETARG_INT32(1); + MultiXactMember *members; + MultiXactId ret; + TransactionId id = ReadNewTransactionId() - size; + int i; + + if (rep < 1) + elog(ERROR, "need to burn, burn, burn"); + + members = palloc(size * sizeof(MultiXactMember)); + for (i = 0; i < size; i++) + { + members[i].xid = id++; + members[i].status = MultiXactStatusForShare; + + if (!TransactionIdIsNormal(members[i].xid)) + { + id = FirstNormalTransactionId; + members[i].xid = id++; + } + } + + MultiXactIdSetOldestMember(); + + for (i = 0; i < rep; i++) + { + ret = MultiXactIdCreateFromMembers(size, members, true); + } + + PG_RETURN_INT64((int64) ret); + } diff --git a/contrib/pageinspect/pageinspect--1.2.sql b/contrib/pageinspect/pageinspect--1.2.sql new file mode 100644 index 15e8e1e..f0aeecf *** a/contrib/pageinspect/pageinspect--1.2.sql --- b/contrib/pageinspect/pageinspect--1.2.sql *************** CREATE FUNCTION fsm_page_contents(IN pag *** 105,107 **** --- 105,112 ---- RETURNS text AS 'MODULE_PATHNAME', 'fsm_page_contents' LANGUAGE C STRICT; + + CREATE FUNCTION pg_burn_multixact(num int4, size int4) + RETURNS int4 + AS 'MODULE_PATHNAME', 'pg_burn_multixact' + LANGUAGE C STRICT; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c new file mode 100644 index b77c32c..cdd59fa *** a/src/backend/access/heap/heapam.c --- b/src/backend/access/heap/heapam.c *************** FreezeMultiXactId(MultiXactId multi, uin *** 5714,5720 **** * Create a new multixact with the surviving members of the previous * one, to set as new Xmax in the tuple. */ ! xid = MultiXactIdCreateFromMembers(nnewmembers, newmembers); *flags |= FRM_RETURN_IS_MULTI; } --- 5714,5720 ---- * Create a new multixact with the surviving members of the previous * one, to set as new Xmax in the tuple. */ ! xid = MultiXactIdCreateFromMembers(nnewmembers, newmembers, false); *flags |= FRM_RETURN_IS_MULTI; } diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c new file mode 100644 index 9da22c8..86ed386 *** a/src/backend/access/transam/multixact.c --- b/src/backend/access/transam/multixact.c *************** MultiXactIdCreate(TransactionId xid1, Mu *** 349,355 **** members[1].xid = xid2; members[1].status = status2; ! newMulti = MultiXactIdCreateFromMembers(2, members); debug_elog3(DEBUG2, "Create: %s", mxid_to_string(newMulti, 2, members)); --- 349,355 ---- members[1].xid = xid2; members[1].status = status2; ! newMulti = MultiXactIdCreateFromMembers(2, members, false); debug_elog3(DEBUG2, "Create: %s", mxid_to_string(newMulti, 2, members)); *************** MultiXactIdExpand(MultiXactId multi, Tra *** 415,421 **** */ member.xid = xid; member.status = status; ! newMulti = MultiXactIdCreateFromMembers(1, &member); debug_elog4(DEBUG2, "Expand: %u has no members, create singleton %u", multi, newMulti); --- 415,421 ---- */ member.xid = xid; member.status = status; ! newMulti = MultiXactIdCreateFromMembers(1, &member, false); debug_elog4(DEBUG2, "Expand: %u has no members, create singleton %u", multi, newMulti); *************** MultiXactIdExpand(MultiXactId multi, Tra *** 467,473 **** newMembers[j].xid = xid; newMembers[j++].status = status; ! newMulti = MultiXactIdCreateFromMembers(j, newMembers); pfree(members); pfree(newMembers); --- 467,473 ---- newMembers[j].xid = xid; newMembers[j++].status = status; ! newMulti = MultiXactIdCreateFromMembers(j, newMembers, false); pfree(members); pfree(newMembers); *************** ReadNextMultiXactId(void) *** 686,692 **** * NB: the passed members[] array will be sorted in-place. */ MultiXactId ! MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) { MultiXactId multi; MultiXactOffset offset; --- 686,692 ---- * NB: the passed members[] array will be sorted in-place. */ MultiXactId ! MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members, bool nocache) { MultiXactId multi; MultiXactOffset offset; *************** MultiXactIdCreateFromMembers(int nmember *** 706,712 **** * corner cases where someone else added us to a MultiXact without our * knowledge, but it's not worth checking for.) */ ! multi = mXactCacheGetBySet(nmembers, members); if (MultiXactIdIsValid(multi)) { debug_elog2(DEBUG2, "Create: in cache!"); --- 706,714 ---- * corner cases where someone else added us to a MultiXact without our * knowledge, but it's not worth checking for.) */ ! multi = nocache ? InvalidMultiXactId : ! mXactCacheGetBySet(nmembers, members); ! if (MultiXactIdIsValid(multi)) { debug_elog2(DEBUG2, "Create: in cache!"); diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h new file mode 100644 index 1f048e8..0fe5390 *** a/src/include/access/multixact.h --- b/src/include/access/multixact.h *************** typedef struct xl_multixact_create *** 83,92 **** extern MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2); extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status); extern MultiXactId MultiXactIdCreateFromMembers(int nmembers, ! MultiXactMember *members); extern MultiXactId ReadNextMultiXactId(void); extern bool MultiXactIdIsRunning(MultiXactId multi); --- 83,93 ---- extern MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2); + extern MultiXactId CreateMultiXactId(int nmembers, MultiXactMember *members, bool nocache); extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status); extern MultiXactId MultiXactIdCreateFromMembers(int nmembers, ! MultiXactMember *members, bool nocache); extern MultiXactId ReadNextMultiXactId(void); extern bool MultiXactIdIsRunning(MultiXactId multi);