|
10 | 10 | * |
11 | 11 | * |
12 | 12 | * IDENTIFICATION |
13 | | - * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.248 2007/09/05 18:10:47 tgl Exp $ |
| 13 | + * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.249 2007/09/07 20:59:26 tgl Exp $ |
14 | 14 | * |
15 | 15 | *------------------------------------------------------------------------- |
16 | 16 | */ |
@@ -747,6 +747,8 @@ AtSubStart_ResourceOwner(void) |
747 | 747 |
|
748 | 748 | /* |
749 | 749 | *RecordTransactionCommit |
| 750 | + * |
| 751 | + * This is exported only to support an ugly hack in VACUUM FULL. |
750 | 752 | */ |
751 | 753 | void |
752 | 754 | RecordTransactionCommit(void) |
@@ -1552,46 +1554,53 @@ CommitTransaction(void) |
1552 | 1554 | */ |
1553 | 1555 | RecordTransactionCommit(); |
1554 | 1556 |
|
1555 | | -/*---------- |
| 1557 | +PG_TRACE1(transaction__commit,MyProc->lxid); |
| 1558 | + |
| 1559 | +/* |
1556 | 1560 | * Let others know about no transaction in progress by me. Note that |
1557 | 1561 | * this must be done _before_ releasing locks we hold and _after_ |
1558 | 1562 | * RecordTransactionCommit. |
1559 | 1563 | * |
1560 | | - * LWLockAcquire(ProcArrayLock) is required; consider this example: |
1561 | | - *UPDATE with xid 0 is blocked by xid 1's UPDATE. |
1562 | | - *xid 1 is doing commit while xid 2 gets snapshot. |
1563 | | - * If xid 2's GetSnapshotData sees xid 1 as running then it must see |
1564 | | - * xid 0 as running as well, or it will be able to see two tuple versions |
1565 | | - * - one deleted by xid 1 and one inserted by xid 0. See notes in |
1566 | | - * GetSnapshotData. |
1567 | | - * |
1568 | 1564 | * Note: MyProc may be null during bootstrap. |
1569 | | - *---------- |
1570 | 1565 | */ |
1571 | 1566 | if (MyProc!=NULL) |
1572 | 1567 | { |
1573 | | -/* |
1574 | | - * Lock ProcArrayLock because that's what GetSnapshotData uses. |
1575 | | - * You might assume that we can skip this step if we had no |
1576 | | - * transaction id assigned, because the failure case outlined |
1577 | | - * in GetSnapshotData cannot happen in that case. This is true, |
1578 | | - * but we *still* need the lock guarantee that two concurrent |
1579 | | - * computations of the *oldest* xmin will get the same result. |
1580 | | - */ |
1581 | | -LWLockAcquire(ProcArrayLock,LW_EXCLUSIVE); |
1582 | | -MyProc->xid=InvalidTransactionId; |
1583 | | -MyProc->lxid=InvalidLocalTransactionId; |
1584 | | -MyProc->xmin=InvalidTransactionId; |
1585 | | -MyProc->inVacuum= false;/* must be cleared with xid/xmin */ |
| 1568 | +if (TransactionIdIsValid(MyProc->xid)) |
| 1569 | +{ |
| 1570 | +/* |
| 1571 | + * We must lock ProcArrayLock while clearing MyProc->xid, so |
| 1572 | + * that we do not exit the set of "running" transactions while |
| 1573 | + * someone else is taking a snapshot. See discussion in |
| 1574 | + * src/backend/access/transam/README. |
| 1575 | + */ |
| 1576 | +LWLockAcquire(ProcArrayLock,LW_EXCLUSIVE); |
1586 | 1577 |
|
1587 | | -/* Clear the subtransaction-XID cache too while holding the lock */ |
1588 | | -MyProc->subxids.nxids=0; |
1589 | | -MyProc->subxids.overflowed= false; |
| 1578 | +MyProc->xid=InvalidTransactionId; |
| 1579 | +MyProc->lxid=InvalidLocalTransactionId; |
| 1580 | +MyProc->xmin=InvalidTransactionId; |
| 1581 | +MyProc->inVacuum= false;/* must be cleared with xid/xmin */ |
1590 | 1582 |
|
1591 | | -LWLockRelease(ProcArrayLock); |
1592 | | -} |
| 1583 | +/* Clear the subtransaction-XID cache too while holding the lock */ |
| 1584 | +MyProc->subxids.nxids=0; |
| 1585 | +MyProc->subxids.overflowed= false; |
1593 | 1586 |
|
1594 | | -PG_TRACE1(transaction__commit,s->transactionId); |
| 1587 | +LWLockRelease(ProcArrayLock); |
| 1588 | +} |
| 1589 | +else |
| 1590 | +{ |
| 1591 | +/* |
| 1592 | + * If we have no XID, we don't need to lock, since we won't |
| 1593 | + * affect anyone else's calculation of a snapshot. We might |
| 1594 | + * change their estimate of global xmin, but that's OK. |
| 1595 | + */ |
| 1596 | +MyProc->lxid=InvalidLocalTransactionId; |
| 1597 | +MyProc->xmin=InvalidTransactionId; |
| 1598 | +MyProc->inVacuum= false;/* must be cleared with xid/xmin */ |
| 1599 | + |
| 1600 | +Assert(MyProc->subxids.nxids==0); |
| 1601 | +Assert(MyProc->subxids.overflowed== false); |
| 1602 | +} |
| 1603 | +} |
1595 | 1604 |
|
1596 | 1605 | /* |
1597 | 1606 | * This is all post-commit cleanup. Note that if an error is raised here, |
@@ -1815,28 +1824,21 @@ PrepareTransaction(void) |
1815 | 1824 | * Let others know about no transaction in progress by me.This has to be |
1816 | 1825 | * done *after* the prepared transaction has been marked valid, else |
1817 | 1826 | * someone may think it is unlocked and recyclable. |
| 1827 | + * |
| 1828 | + * We can skip locking ProcArrayLock here, because this action does not |
| 1829 | + * actually change anyone's view of the set of running XIDs: our entry |
| 1830 | + * is duplicate with the gxact that has already been inserted into the |
| 1831 | + * ProcArray. |
1818 | 1832 | */ |
1819 | | - |
1820 | | -/* |
1821 | | - * Lock ProcArrayLock because that's what GetSnapshotData uses. |
1822 | | - * You might assume that we can skip this step if we have no |
1823 | | - * transaction id assigned, because the failure case outlined |
1824 | | - * in GetSnapshotData cannot happen in that case. This is true, |
1825 | | - * but we *still* need the lock guarantee that two concurrent |
1826 | | - * computations of the *oldest* xmin will get the same result. |
1827 | | - */ |
1828 | | -LWLockAcquire(ProcArrayLock,LW_EXCLUSIVE); |
1829 | 1833 | MyProc->xid=InvalidTransactionId; |
1830 | 1834 | MyProc->lxid=InvalidLocalTransactionId; |
1831 | 1835 | MyProc->xmin=InvalidTransactionId; |
1832 | 1836 | MyProc->inVacuum= false;/* must be cleared with xid/xmin */ |
1833 | 1837 |
|
1834 | | -/* Clear the subtransaction-XID cache toowhile holding the lock*/ |
| 1838 | +/* Clear the subtransaction-XID cache too */ |
1835 | 1839 | MyProc->subxids.nxids=0; |
1836 | 1840 | MyProc->subxids.overflowed= false; |
1837 | 1841 |
|
1838 | | -LWLockRelease(ProcArrayLock); |
1839 | | - |
1840 | 1842 | /* |
1841 | 1843 | * This is all post-transaction cleanup. Note that if an error is raised |
1842 | 1844 | * here, it's too late to abort the transaction. This should be just |
@@ -1987,36 +1989,55 @@ AbortTransaction(void) |
1987 | 1989 | */ |
1988 | 1990 | RecordTransactionAbort(false); |
1989 | 1991 |
|
| 1992 | +PG_TRACE1(transaction__abort,MyProc->lxid); |
| 1993 | + |
1990 | 1994 | /* |
1991 | 1995 | * Let others know about no transaction in progress by me. Note that this |
1992 | 1996 | * must be done _before_ releasing locks we hold and _after_ |
1993 | 1997 | * RecordTransactionAbort. |
| 1998 | + * |
| 1999 | + * Note: MyProc may be null during bootstrap. |
1994 | 2000 | */ |
1995 | 2001 | if (MyProc!=NULL) |
1996 | 2002 | { |
1997 | | -/* |
1998 | | - * Lock ProcArrayLock because that's what GetSnapshotData uses. |
1999 | | - * You might assume that we can skip this step if we have no |
2000 | | - * transaction id assigned, because the failure case outlined |
2001 | | - * in GetSnapshotData cannot happen in that case. This is true, |
2002 | | - * but we *still* need the lock guarantee that two concurrent |
2003 | | - * computations of the *oldest* xmin will get the same result. |
2004 | | - */ |
2005 | | -LWLockAcquire(ProcArrayLock,LW_EXCLUSIVE); |
2006 | | -MyProc->xid=InvalidTransactionId; |
2007 | | -MyProc->lxid=InvalidLocalTransactionId; |
2008 | | -MyProc->xmin=InvalidTransactionId; |
2009 | | -MyProc->inVacuum= false;/* must be cleared with xid/xmin */ |
2010 | | -MyProc->inCommit= false;/* be sure this gets cleared */ |
2011 | | - |
2012 | | -/* Clear the subtransaction-XID cache too while holding the lock */ |
2013 | | -MyProc->subxids.nxids=0; |
2014 | | -MyProc->subxids.overflowed= false; |
2015 | | - |
2016 | | -LWLockRelease(ProcArrayLock); |
2017 | | -} |
| 2003 | +if (TransactionIdIsValid(MyProc->xid)) |
| 2004 | +{ |
| 2005 | +/* |
| 2006 | + * We must lock ProcArrayLock while clearing MyProc->xid, so |
| 2007 | + * that we do not exit the set of "running" transactions while |
| 2008 | + * someone else is taking a snapshot. See discussion in |
| 2009 | + * src/backend/access/transam/README. |
| 2010 | + */ |
| 2011 | +LWLockAcquire(ProcArrayLock,LW_EXCLUSIVE); |
2018 | 2012 |
|
2019 | | -PG_TRACE1(transaction__abort,s->transactionId); |
| 2013 | +MyProc->xid=InvalidTransactionId; |
| 2014 | +MyProc->lxid=InvalidLocalTransactionId; |
| 2015 | +MyProc->xmin=InvalidTransactionId; |
| 2016 | +MyProc->inVacuum= false;/* must be cleared with xid/xmin */ |
| 2017 | +MyProc->inCommit= false;/* be sure this gets cleared */ |
| 2018 | + |
| 2019 | +/* Clear the subtransaction-XID cache too while holding the lock */ |
| 2020 | +MyProc->subxids.nxids=0; |
| 2021 | +MyProc->subxids.overflowed= false; |
| 2022 | + |
| 2023 | +LWLockRelease(ProcArrayLock); |
| 2024 | +} |
| 2025 | +else |
| 2026 | +{ |
| 2027 | +/* |
| 2028 | + * If we have no XID, we don't need to lock, since we won't |
| 2029 | + * affect anyone else's calculation of a snapshot. We might |
| 2030 | + * change their estimate of global xmin, but that's OK. |
| 2031 | + */ |
| 2032 | +MyProc->lxid=InvalidLocalTransactionId; |
| 2033 | +MyProc->xmin=InvalidTransactionId; |
| 2034 | +MyProc->inVacuum= false;/* must be cleared with xid/xmin */ |
| 2035 | +MyProc->inCommit= false;/* be sure this gets cleared */ |
| 2036 | + |
| 2037 | +Assert(MyProc->subxids.nxids==0); |
| 2038 | +Assert(MyProc->subxids.overflowed== false); |
| 2039 | +} |
| 2040 | +} |
2020 | 2041 |
|
2021 | 2042 | /* |
2022 | 2043 | * Post-abort cleanup.See notes in CommitTransaction() concerning |
|