|
10 | 10 | * |
11 | 11 | * |
12 | 12 | * IDENTIFICATION |
13 | | - * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.253 2007/11/15 21:14:32 momjian Exp $ |
| 13 | + * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.254 2007/11/30 21:22:53 tgl Exp $ |
14 | 14 | * |
15 | 15 | *------------------------------------------------------------------------- |
16 | 16 | */ |
@@ -161,6 +161,7 @@ static TransactionState CurrentTransactionState = &TopTransactionStateData; |
161 | 161 | */ |
162 | 162 | staticSubTransactionIdcurrentSubTransactionId; |
163 | 163 | staticCommandIdcurrentCommandId; |
| 164 | +staticboolcurrentCommandIdUsed; |
164 | 165 |
|
165 | 166 | /* |
166 | 167 | * xactStartTimestamp is the value of transaction_timestamp(). |
@@ -435,11 +436,18 @@ GetCurrentSubTransactionId(void) |
435 | 436 |
|
436 | 437 | /* |
437 | 438 | *GetCurrentCommandId |
| 439 | + * |
| 440 | + * "used" must be TRUE if the caller intends to use the command ID to mark |
| 441 | + * inserted/updated/deleted tuples. FALSE means the ID is being fetched |
| 442 | + * for read-only purposes (ie, as a snapshot validity cutoff). See |
| 443 | + * CommandCounterIncrement() for discussion. |
438 | 444 | */ |
439 | 445 | CommandId |
440 | | -GetCurrentCommandId(void) |
| 446 | +GetCurrentCommandId(boolused) |
441 | 447 | { |
442 | 448 | /* this is global to a transaction, not subtransaction-local */ |
| 449 | +if (used) |
| 450 | +currentCommandIdUsed= true; |
443 | 451 | returncurrentCommandId; |
444 | 452 | } |
445 | 453 |
|
@@ -566,25 +574,50 @@ TransactionIdIsCurrentTransactionId(TransactionId xid) |
566 | 574 | void |
567 | 575 | CommandCounterIncrement(void) |
568 | 576 | { |
569 | | -currentCommandId+=1; |
570 | | -if (currentCommandId==FirstCommandId)/* check for overflow */ |
| 577 | +/* |
| 578 | + * If the current value of the command counter hasn't been "used" to |
| 579 | + * mark tuples, we need not increment it, since there's no need to |
| 580 | + * distinguish a read-only command from others. This helps postpone |
| 581 | + * command counter overflow, and keeps no-op CommandCounterIncrement |
| 582 | + * operations cheap. |
| 583 | + */ |
| 584 | +if (currentCommandIdUsed) |
571 | 585 | { |
572 | | -currentCommandId-=1; |
573 | | -ereport(ERROR, |
574 | | -(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), |
| 586 | +currentCommandId+=1; |
| 587 | +if (currentCommandId==FirstCommandId)/* check for overflow */ |
| 588 | +{ |
| 589 | +currentCommandId-=1; |
| 590 | +ereport(ERROR, |
| 591 | +(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), |
575 | 592 | errmsg("cannot have more than 2^32-1 commands in a transaction"))); |
576 | | -} |
| 593 | +} |
| 594 | +currentCommandIdUsed= false; |
577 | 595 |
|
578 | | -/* Propagate new command ID into static snapshots, if set */ |
579 | | -if (SerializableSnapshot) |
580 | | -SerializableSnapshot->curcid=currentCommandId; |
581 | | -if (LatestSnapshot) |
582 | | -LatestSnapshot->curcid=currentCommandId; |
| 596 | +/* Propagate new command ID into static snapshots, if set */ |
| 597 | +if (SerializableSnapshot) |
| 598 | +SerializableSnapshot->curcid=currentCommandId; |
| 599 | +if (LatestSnapshot) |
| 600 | +LatestSnapshot->curcid=currentCommandId; |
| 601 | + |
| 602 | +/* |
| 603 | + * Make any catalog changes done by the just-completed command |
| 604 | + * visible in the local syscache. We obviously don't need to do |
| 605 | + * this after a read-only command. (But see hacks in inval.c |
| 606 | + * to make real sure we don't think a command that queued inval |
| 607 | + * messages was read-only.) |
| 608 | + */ |
| 609 | +AtCommit_LocalCache(); |
| 610 | +} |
583 | 611 |
|
584 | 612 | /* |
585 | | - * make cache changes visible to me. |
| 613 | + * Make any other backends' catalog changes visible to me. |
| 614 | + * |
| 615 | + * XXX this is probably in the wrong place: CommandCounterIncrement |
| 616 | + * should be purely a local operation, most likely. However fooling |
| 617 | + * with this will affect asynchronous cross-backend interactions, |
| 618 | + * which doesn't seem like a wise thing to do in late beta, so save |
| 619 | + * improving this for another day - tgl 2007-11-30 |
586 | 620 | */ |
587 | | -AtCommit_LocalCache(); |
588 | 621 | AtStart_Cache(); |
589 | 622 | } |
590 | 623 |
|
@@ -1416,6 +1449,7 @@ StartTransaction(void) |
1416 | 1449 | s->subTransactionId=TopSubTransactionId; |
1417 | 1450 | currentSubTransactionId=TopSubTransactionId; |
1418 | 1451 | currentCommandId=FirstCommandId; |
| 1452 | +currentCommandIdUsed= false; |
1419 | 1453 |
|
1420 | 1454 | /* |
1421 | 1455 | * must initialize resource-management stuff first |
@@ -4007,13 +4041,14 @@ ShowTransactionStateRec(TransactionState s) |
4007 | 4041 |
|
4008 | 4042 | /* use ereport to suppress computation if msg will not be printed */ |
4009 | 4043 | ereport(DEBUG3, |
4010 | | -(errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s", |
| 4044 | +(errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s", |
4011 | 4045 | PointerIsValid(s->name) ?s->name :"unnamed", |
4012 | 4046 | BlockStateAsString(s->blockState), |
4013 | 4047 | TransStateAsString(s->state), |
4014 | 4048 | (unsignedint)s->transactionId, |
4015 | 4049 | (unsignedint)s->subTransactionId, |
4016 | 4050 | (unsignedint)currentCommandId, |
| 4051 | +currentCommandIdUsed ?" (used)" :"", |
4017 | 4052 | s->nestingLevel, |
4018 | 4053 | nodeToString(s->childXids)))); |
4019 | 4054 | } |
|