mirror of
https://github.com/postgres/postgres.git
synced 2025-11-13 16:22:44 +03:00
Revise ResourceOwner code to avoid accumulating ResourceOwner objects
for every command executed within a transaction. For long transactions this was a significant memory leak. Instead, we can delete a portal's or subtransaction's ResourceOwner immediately, if we physically transfer the information about its locks up to the parent owner. This does not fully solve the leak problem; we need to do something about counting multiple acquisitions of the same lock in order to fix it. But it's a necessary step along the way.
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.68 2004/08/02 21:42:18 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.69 2004/08/25 18:43:43 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -354,8 +354,7 @@ PortalDrop(Portal portal, bool isTopCommit)
|
||||
ResourceOwnerRelease(portal->resowner,
|
||||
RESOURCE_RELEASE_AFTER_LOCKS,
|
||||
isCommit, false);
|
||||
if (!isCommit)
|
||||
ResourceOwnerDelete(portal->resowner);
|
||||
ResourceOwnerDelete(portal->resowner);
|
||||
}
|
||||
portal->resowner = NULL;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$PostgreSQL: pgsql/src/backend/utils/resowner/README,v 1.2 2004/07/31 00:45:40 tgl Exp $
|
||||
$PostgreSQL: pgsql/src/backend/utils/resowner/README,v 1.3 2004/08/25 18:43:43 tgl Exp $
|
||||
|
||||
Notes about resource owners
|
||||
---------------------------
|
||||
@@ -30,8 +30,9 @@ ownership of the acquired resources in that ResourceOwner object.
|
||||
When a Portal is closed, any remaining resources (typically only locks)
|
||||
become the responsibility of the current transaction. This is represented
|
||||
by making the Portal's ResourceOwner a child of the current transaction's
|
||||
ResourceOwner. Similarly, subtransaction ResourceOwners are children of
|
||||
their immediate parent.
|
||||
ResourceOwner. resowner.c automatically transfers the resources to the
|
||||
parent object when releasing the child. Similarly, subtransaction
|
||||
ResourceOwners are children of their immediate parent.
|
||||
|
||||
We need transaction-related ResourceOwners as well as Portal-related ones
|
||||
because transactions may initiate operations that require resources (such
|
||||
@@ -53,6 +54,12 @@ The basic operations on a ResourceOwner are:
|
||||
* delete a ResourceOwner (including child owner objects); all resources
|
||||
must have been released beforehand
|
||||
|
||||
Locks are handled specially because in non-error situations a lock should
|
||||
be held until end of transaction, even if it was originally taken by a
|
||||
subtransaction or portal. Therefore, the "release" operation on a child
|
||||
ResourceOwner transfers lock ownership to the parent instead of actually
|
||||
releasing the lock, if isCommit is true.
|
||||
|
||||
Currently, ResourceOwners contain direct support for recording ownership
|
||||
of buffer pins, lmgr locks, and catcache and relcache references. Other
|
||||
objects can be associated with a ResourceOwner by recording the address of
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.2 2004/07/31 00:45:40 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.3 2004/08/25 18:43:43 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -277,25 +277,40 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
|
||||
/* Mark object as holding no locks, just for sanity */
|
||||
owner->nlocks = 0;
|
||||
}
|
||||
else if (!isCommit)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Release locks retail. Note that LockRelease will remove
|
||||
* the lock entry from my list, so I just have to iterate till
|
||||
* there are none. Also note that if we are committing a
|
||||
* subtransaction, we do NOT release its locks yet.
|
||||
* subtransaction, we do NOT release its locks yet, but transfer
|
||||
* them to the parent.
|
||||
*
|
||||
* XXX as above, this is a bit inefficient but probably not worth
|
||||
* the trouble to optimize more.
|
||||
*/
|
||||
Assert(owner->parent != NULL);
|
||||
while (owner->nlocks > 0)
|
||||
{
|
||||
LockIdData *lockid = &owner->locks[owner->nlocks - 1];
|
||||
|
||||
LockRelease(lockid->locktag.lockmethodid,
|
||||
&lockid->locktag,
|
||||
lockid->xid,
|
||||
lockid->lockmode);
|
||||
if (isCommit)
|
||||
{
|
||||
ResourceOwnerEnlargeLocks(owner->parent);
|
||||
ResourceOwnerRememberLock(owner->parent,
|
||||
&lockid->locktag,
|
||||
lockid->xid,
|
||||
lockid->lockmode);
|
||||
owner->nlocks--;
|
||||
}
|
||||
else
|
||||
{
|
||||
LockRelease(lockid->locktag.lockmethodid,
|
||||
&lockid->locktag,
|
||||
lockid->xid,
|
||||
lockid->lockmode);
|
||||
/* LockRelease will have removed the entry from list */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user