Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit32846f8

Browse files
committed
Fix TransactionIdIsCurrentTransactionId() to use binary search instead of
linear search when checking child-transaction XIDs. This makes for animportant speedup in transactions that have large numbers of children,as in a recent example from Craig Ringer. We can also get rid of anugly kluge that represented lists of TransactionIds as lists of OIDs.Heikki Linnakangas
1 parenta7c58ab commit32846f8

File tree

3 files changed

+128
-72
lines changed

3 files changed

+128
-72
lines changed

‎src/backend/access/transam/twophase.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
*$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.39 2008/01/01 19:45:48 momjian Exp $
10+
*$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.40 2008/03/17 02:18:55 tgl Exp $
1111
*
1212
* NOTES
1313
*Each global transaction is associated with a global transaction
@@ -827,7 +827,6 @@ StartPrepare(GlobalTransaction gxact)
827827
save_state_data(children,hdr.nsubxacts*sizeof(TransactionId));
828828
/* While we have the child-xact data, stuff it in the gxact too */
829829
GXactLoadSubxactData(gxact,hdr.nsubxacts,children);
830-
pfree(children);
831830
}
832831
if (hdr.ncommitrels>0)
833832
{

‎src/backend/access/transam/xact.c

Lines changed: 126 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.258 2008/03/04 19:54:06 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.259 2008/03/17 02:18:55 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -130,7 +130,9 @@ typedef struct TransactionStateData
130130
intgucNestLevel;/* GUC context nesting depth */
131131
MemoryContextcurTransactionContext;/* my xact-lifetime context */
132132
ResourceOwnercurTransactionOwner;/* my query resources */
133-
List*childXids;/* subcommitted child XIDs */
133+
TransactionId*childXids;/* subcommitted child XIDs, in XID order */
134+
intnChildXids;/* # of subcommitted child XIDs */
135+
intmaxChildXids;/* allocated size of childXids[] */
134136
OidprevUser;/* previous CurrentUserId setting */
135137
boolprevSecDefCxt;/* previous SecurityDefinerContext setting */
136138
boolprevXactReadOnly;/* entry-time xact r/o state */
@@ -156,7 +158,9 @@ static TransactionStateData TopTransactionStateData = {
156158
0,/* GUC context nesting depth */
157159
NULL,/* cur transaction context */
158160
NULL,/* cur transaction resource owner */
159-
NIL,/* subcommitted child Xids */
161+
NULL,/* subcommitted child Xids */
162+
0,/* # of subcommitted child Xids */
163+
0,/* allocated size of childXids[] */
160164
InvalidOid,/* previous CurrentUserId setting */
161165
false,/* previous SecurityDefinerContext setting */
162166
false,/* entry-time xact r/o state */
@@ -559,18 +563,30 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
559563
*/
560564
for (s=CurrentTransactionState;s!=NULL;s=s->parent)
561565
{
562-
ListCell*cell;
566+
intlow,high;
563567

564568
if (s->state==TRANS_ABORT)
565569
continue;
566570
if (!TransactionIdIsValid(s->transactionId))
567571
continue;/* it can't have any child XIDs either */
568572
if (TransactionIdEquals(xid,s->transactionId))
569573
return true;
570-
foreach(cell,s->childXids)
574+
/* As the childXids array is ordered, we can use binary search */
575+
low=0;
576+
high=s->nChildXids-1;
577+
while (low <=high)
571578
{
572-
if (TransactionIdEquals(xid,lfirst_xid(cell)))
579+
intmiddle;
580+
TransactionIdprobe;
581+
582+
middle=low+ (high-low) /2;
583+
probe=s->childXids[middle];
584+
if (TransactionIdEquals(probe,xid))
573585
return true;
586+
elseif (TransactionIdPrecedes(probe,xid))
587+
low=middle+1;
588+
else
589+
high=middle-1;
574590
}
575591
}
576592

@@ -985,8 +1001,6 @@ RecordTransactionCommit(void)
9851001
/* Clean up local data */
9861002
if (rels)
9871003
pfree(rels);
988-
if (children)
989-
pfree(children);
9901004

9911005
returnlatestXid;
9921006
}
@@ -1067,34 +1081,79 @@ static void
10671081
AtSubCommit_childXids(void)
10681082
{
10691083
TransactionStates=CurrentTransactionState;
1070-
MemoryContextold_cxt;
1084+
intnew_nChildXids;
10711085

10721086
Assert(s->parent!=NULL);
10731087

10741088
/*
1075-
* We keep the child-XID lists in TopTransactionContext; this avoids
1076-
* setting up child-transaction contexts for what might be just a few
1077-
* bytes of grandchild XIDs.
1089+
* The parent childXids array will need to hold my XID and all my
1090+
* childXids, in addition to the XIDs already there.
10781091
*/
1079-
old_cxt=MemoryContextSwitchTo(TopTransactionContext);
1080-
1081-
s->parent->childXids=lappend_xid(s->parent->childXids,
1082-
s->transactionId);
1092+
new_nChildXids=s->parent->nChildXids+s->nChildXids+1;
10831093

1084-
if (s->childXids!=NIL)
1094+
/* Allocate or enlarge the parent array if necessary */
1095+
if (s->parent->maxChildXids<new_nChildXids)
10851096
{
1086-
s->parent->childXids=list_concat(s->parent->childXids,
1087-
s->childXids);
1097+
intnew_maxChildXids;
1098+
TransactionId*new_childXids;
10881099

10891100
/*
1090-
* list_concat doesn't free the list header for the second list; do so
1091-
* here to avoid memory leakage (kluge)
1101+
* Make it 2x what's needed right now, to avoid having to enlarge it
1102+
* repeatedly. But we can't go above MaxAllocSize. (The latter
1103+
* limit is what ensures that we don't need to worry about integer
1104+
* overflow here or in the calculation of new_nChildXids.)
10921105
*/
1093-
pfree(s->childXids);
1094-
s->childXids=NIL;
1106+
new_maxChildXids=Min(new_nChildXids*2,
1107+
(int) (MaxAllocSize /sizeof(TransactionId)));
1108+
1109+
if (new_maxChildXids<new_nChildXids)
1110+
ereport(ERROR,
1111+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1112+
errmsg("maximum number of committed subtransactions (%d) exceeded",
1113+
(int) (MaxAllocSize /sizeof(TransactionId)))));
1114+
1115+
/*
1116+
* We keep the child-XID arrays in TopTransactionContext; this avoids
1117+
* setting up child-transaction contexts for what might be just a few
1118+
* bytes of grandchild XIDs.
1119+
*/
1120+
if (s->parent->childXids==NULL)
1121+
new_childXids=
1122+
MemoryContextAlloc(TopTransactionContext,
1123+
new_maxChildXids*sizeof(TransactionId));
1124+
else
1125+
new_childXids=repalloc(s->parent->childXids,
1126+
new_maxChildXids*sizeof(TransactionId));
1127+
1128+
s->parent->childXids=new_childXids;
1129+
s->parent->maxChildXids=new_maxChildXids;
10951130
}
10961131

1097-
MemoryContextSwitchTo(old_cxt);
1132+
/*
1133+
* Copy all my XIDs to parent's array.
1134+
*
1135+
* Note: We rely on the fact that the XID of a child always follows that
1136+
* of its parent. By copying the XID of this subtransaction before the
1137+
* XIDs of its children, we ensure that the array stays ordered. Likewise,
1138+
* all XIDs already in the array belong to subtransactions started and
1139+
* subcommitted before us, so their XIDs must precede ours.
1140+
*/
1141+
s->parent->childXids[s->parent->nChildXids]=s->transactionId;
1142+
1143+
if (s->nChildXids>0)
1144+
memcpy(&s->parent->childXids[s->parent->nChildXids+1],
1145+
s->childXids,
1146+
s->nChildXids*sizeof(TransactionId));
1147+
1148+
s->parent->nChildXids=new_nChildXids;
1149+
1150+
/* Release child's array to avoid leakage */
1151+
if (s->childXids!=NULL)
1152+
pfree(s->childXids);
1153+
/* We must reset these to avoid double-free if fail later in commit */
1154+
s->childXids=NULL;
1155+
s->nChildXids=0;
1156+
s->maxChildXids=0;
10981157
}
10991158

11001159
/*
@@ -1259,8 +1318,6 @@ RecordTransactionAbort(bool isSubXact)
12591318
/* And clean up local data */
12601319
if (rels)
12611320
pfree(rels);
1262-
if (children)
1263-
pfree(children);
12641321

12651322
returnlatestXid;
12661323
}
@@ -1332,12 +1389,15 @@ AtSubAbort_childXids(void)
13321389
TransactionStates=CurrentTransactionState;
13331390

13341391
/*
1335-
* We keep the child-XIDlists in TopTransactionContext (see
1336-
* AtSubCommit_childXids).This means we'd better free thelist
1392+
* We keep the child-XIDarrays in TopTransactionContext (see
1393+
* AtSubCommit_childXids).This means we'd better free thearray
13371394
* explicitly at abort to avoid leakage.
13381395
*/
1339-
list_free(s->childXids);
1340-
s->childXids=NIL;
1396+
if (s->childXids!=NULL)
1397+
pfree(s->childXids);
1398+
s->childXids=NULL;
1399+
s->nChildXids=0;
1400+
s->maxChildXids=0;
13411401
}
13421402

13431403
/* ----------------------------------------------------------------
@@ -1506,7 +1566,9 @@ StartTransaction(void)
15061566
*/
15071567
s->nestingLevel=1;
15081568
s->gucNestLevel=1;
1509-
s->childXids=NIL;
1569+
s->childXids=NULL;
1570+
s->nChildXids=0;
1571+
s->maxChildXids=0;
15101572
GetUserIdAndContext(&s->prevUser,&s->prevSecDefCxt);
15111573
/* SecurityDefinerContext should never be set outside a transaction */
15121574
Assert(!s->prevSecDefCxt);
@@ -1702,7 +1764,9 @@ CommitTransaction(void)
17021764
s->subTransactionId=InvalidSubTransactionId;
17031765
s->nestingLevel=0;
17041766
s->gucNestLevel=0;
1705-
s->childXids=NIL;
1767+
s->childXids=NULL;
1768+
s->nChildXids=0;
1769+
s->maxChildXids=0;
17061770

17071771
/*
17081772
* done with commit processing, set current transaction state back to
@@ -1931,7 +1995,9 @@ PrepareTransaction(void)
19311995
s->subTransactionId=InvalidSubTransactionId;
19321996
s->nestingLevel=0;
19331997
s->gucNestLevel=0;
1934-
s->childXids=NIL;
1998+
s->childXids=NULL;
1999+
s->nChildXids=0;
2000+
s->maxChildXids=0;
19352001

19362002
/*
19372003
* done with 1st phase commit processing, set current transaction state
@@ -2101,7 +2167,9 @@ CleanupTransaction(void)
21012167
s->subTransactionId=InvalidSubTransactionId;
21022168
s->nestingLevel=0;
21032169
s->gucNestLevel=0;
2104-
s->childXids=NIL;
2170+
s->childXids=NULL;
2171+
s->nChildXids=0;
2172+
s->maxChildXids=0;
21052173

21062174
/*
21072175
* done with abort processing, set current transaction state back to
@@ -4051,6 +4119,19 @@ ShowTransactionState(const char *str)
40514119
staticvoid
40524120
ShowTransactionStateRec(TransactionStates)
40534121
{
4122+
StringInfoDatabuf;
4123+
4124+
initStringInfo(&buf);
4125+
4126+
if (s->nChildXids>0)
4127+
{
4128+
inti;
4129+
4130+
appendStringInfo(&buf,"%u",s->childXids[0]);
4131+
for (i=1;i<s->nChildXids;i++)
4132+
appendStringInfo(&buf," %u",s->childXids[i]);
4133+
}
4134+
40544135
if (s->parent)
40554136
ShowTransactionStateRec(s->parent);
40564137

@@ -4064,8 +4145,9 @@ ShowTransactionStateRec(TransactionState s)
40644145
(unsignedint)s->subTransactionId,
40654146
(unsignedint)currentCommandId,
40664147
currentCommandIdUsed ?" (used)" :"",
4067-
s->nestingLevel,
4068-
nodeToString(s->childXids))));
4148+
s->nestingLevel,buf.data)));
4149+
4150+
pfree(buf.data);
40694151
}
40704152

40714153
/*
@@ -4144,36 +4226,22 @@ TransStateAsString(TransState state)
41444226
* xactGetCommittedChildren
41454227
*
41464228
* Gets the list of committed children of the current transaction.The return
4147-
* value is the number of child transactions. *children is set to point to a
4148-
* palloc'd array of TransactionIds. If there are no subxacts, *children is
4149-
* set to NULL.
4229+
* value is the number of child transactions. *ptr is set to point to an
4230+
* array of TransactionIds. The array is allocated in TopTransactionContext;
4231+
* the caller should *not* pfree() it (this is a change from pre-8.4 code!).
4232+
* If there are no subxacts, *ptr is set to NULL.
41504233
*/
41514234
int
41524235
xactGetCommittedChildren(TransactionId**ptr)
41534236
{
41544237
TransactionStates=CurrentTransactionState;
4155-
intnchildren;
4156-
TransactionId*children;
4157-
ListCell*p;
41584238

4159-
nchildren=list_length(s->childXids);
4160-
if (nchildren==0)
4161-
{
4239+
if (s->nChildXids==0)
41624240
*ptr=NULL;
4163-
return0;
4164-
}
4165-
4166-
children= (TransactionId*)palloc(nchildren*sizeof(TransactionId));
4167-
*ptr=children;
4168-
4169-
foreach(p,s->childXids)
4170-
{
4171-
TransactionIdchild=lfirst_xid(p);
4172-
4173-
*children++=child;
4174-
}
4241+
else
4242+
*ptr=s->childXids;
41754243

4176-
returnnchildren;
4244+
returns->nChildXids;
41774245
}
41784246

41794247
/*

‎src/include/nodes/pg_list.h

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,11 @@
2626
* (At the moment, ints and Oids are the same size, but they may not
2727
* always be so; try to be careful to maintain the distinction.)
2828
*
29-
* There is also limited support for lists of TransactionIds; since these
30-
* are used in only one or two places, we don't provide a full implementation,
31-
* but map them onto Oid lists. This effectively assumes that TransactionId
32-
* is no wider than Oid and both are unsigned types.
33-
*
3429
*
3530
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
3631
* Portions Copyright (c) 1994, Regents of the University of California
3732
*
38-
* $PostgreSQL: pgsql/src/include/nodes/pg_list.h,v 1.57 2008/01/01 19:45:58 momjian Exp $
33+
* $PostgreSQL: pgsql/src/include/nodes/pg_list.h,v 1.58 2008/03/17 02:18:55 tgl Exp $
3934
*
4035
*-------------------------------------------------------------------------
4136
*/
@@ -159,12 +154,6 @@ extern intlist_length(List *l);
159154
#definelist_make3_oid(x1,x2,x3)lcons_oid(x1, list_make2_oid(x2, x3))
160155
#definelist_make4_oid(x1,x2,x3,x4) lcons_oid(x1, list_make3_oid(x2, x3, x4))
161156

162-
/*
163-
* Limited support for lists of TransactionIds, mapped onto lists of Oids
164-
*/
165-
#definelfirst_xid(lc)((TransactionId) lfirst_oid(lc))
166-
#definelappend_xid(list,datum)lappend_oid(list, (Oid) (datum))
167-
168157
/*
169158
* foreach -
170159
* a convenience macro which loops through the list

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp