mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Implement lazy XID allocation: transactions that do not modify any database
rows will normally never obtain an XID at all. We already did things this way for subtransactions, but this patch extends the concept to top-level transactions. In applications where there are lots of short read-only transactions, this should improve performance noticeably; not so much from removal of the actual XID-assignments, as from reduction of overhead that's driven by the rate of XID consumption. We add a concept of a "virtual transaction ID" so that active transactions can be uniquely identified even if they don't have a regular XID. This is a much lighter-weight concept: uniqueness of VXIDs is only guaranteed over the short term, and no on-disk record is made about them. Florian Pflug, with some editorialization by Tom.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.92 2007/07/25 22:16:18 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.93 2007/09/05 18:10:47 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -421,8 +421,8 @@ UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
|
||||
* XactLockTableInsert
|
||||
*
|
||||
* Insert a lock showing that the given transaction ID is running ---
|
||||
* this is done during xact startup. The lock can then be used to wait
|
||||
* for the transaction to finish.
|
||||
* this is done when an XID is acquired by a transaction or subtransaction.
|
||||
* The lock can then be used to wait for the transaction to finish.
|
||||
*/
|
||||
void
|
||||
XactLockTableInsert(TransactionId xid)
|
||||
@@ -439,8 +439,7 @@ XactLockTableInsert(TransactionId xid)
|
||||
*
|
||||
* Delete the lock showing that the given transaction ID is running.
|
||||
* (This is never used for main transaction IDs; those locks are only
|
||||
* released implicitly at transaction end. But we do use it for subtrans
|
||||
* IDs.)
|
||||
* released implicitly at transaction end. But we do use it for subtrans IDs.)
|
||||
*/
|
||||
void
|
||||
XactLockTableDelete(TransactionId xid)
|
||||
@@ -472,7 +471,7 @@ XactLockTableWait(TransactionId xid)
|
||||
for (;;)
|
||||
{
|
||||
Assert(TransactionIdIsValid(xid));
|
||||
Assert(!TransactionIdEquals(xid, GetTopTransactionId()));
|
||||
Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
|
||||
|
||||
SET_LOCKTAG_TRANSACTION(tag, xid);
|
||||
|
||||
@@ -500,7 +499,7 @@ ConditionalXactLockTableWait(TransactionId xid)
|
||||
for (;;)
|
||||
{
|
||||
Assert(TransactionIdIsValid(xid));
|
||||
Assert(!TransactionIdEquals(xid, GetTopTransactionId()));
|
||||
Assert(!TransactionIdEquals(xid, GetTopTransactionIdIfAny()));
|
||||
|
||||
SET_LOCKTAG_TRANSACTION(tag, xid);
|
||||
|
||||
@@ -517,6 +516,70 @@ ConditionalXactLockTableWait(TransactionId xid)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* VirtualXactLockTableInsert
|
||||
*
|
||||
* Insert a lock showing that the given virtual transaction ID is running ---
|
||||
* this is done at main transaction start when its VXID is assigned.
|
||||
* The lock can then be used to wait for the transaction to finish.
|
||||
*/
|
||||
void
|
||||
VirtualXactLockTableInsert(VirtualTransactionId vxid)
|
||||
{
|
||||
LOCKTAG tag;
|
||||
|
||||
Assert(VirtualTransactionIdIsValid(vxid));
|
||||
|
||||
SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
|
||||
|
||||
(void) LockAcquire(&tag, ExclusiveLock, false, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* VirtualXactLockTableWait
|
||||
*
|
||||
* Waits until the lock on the given VXID is released, which shows that
|
||||
* the top-level transaction owning the VXID has ended.
|
||||
*/
|
||||
void
|
||||
VirtualXactLockTableWait(VirtualTransactionId vxid)
|
||||
{
|
||||
LOCKTAG tag;
|
||||
|
||||
Assert(VirtualTransactionIdIsValid(vxid));
|
||||
|
||||
SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
|
||||
|
||||
(void) LockAcquire(&tag, ShareLock, false, false);
|
||||
|
||||
LockRelease(&tag, ShareLock, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* ConditionalVirtualXactLockTableWait
|
||||
*
|
||||
* As above, but only lock if we can get the lock without blocking.
|
||||
* Returns TRUE if the lock was acquired.
|
||||
*/
|
||||
bool
|
||||
ConditionalVirtualXactLockTableWait(VirtualTransactionId vxid)
|
||||
{
|
||||
LOCKTAG tag;
|
||||
|
||||
Assert(VirtualTransactionIdIsValid(vxid));
|
||||
|
||||
SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
|
||||
|
||||
if (LockAcquire(&tag, ShareLock, false, true) == LOCKACQUIRE_NOT_AVAIL)
|
||||
return false;
|
||||
|
||||
LockRelease(&tag, ShareLock, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LockDatabaseObject
|
||||
*
|
||||
|
Reference in New Issue
Block a user