1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Fix relcache to account properly for subtransaction status of 'new'

relcache entries.  Also, change TransactionIdIsCurrentTransactionId()
so that if consulted during transaction abort, it will not say that
the aborted xact is still current.  (It would be better to ensure that
it's never called at all during abort, but I'm not sure we can easily
guarantee that.)  In combination, these fix a crash we have seen
occasionally during parallel regression tests of 8.0.
This commit is contained in:
Tom Lane
2004-08-28 20:31:44 +00:00
parent f900af7961
commit 1c72d0dec1
7 changed files with 132 additions and 55 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.43 2003/11/29 19:51:40 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.44 2004/08/28 20:31:43 tgl Exp $
*
* NOTES
* Postgres hash pages look like ordinary relation pages. The opaque
@@ -44,14 +44,12 @@ static void _hash_splitbucket(Relation rel, Buffer metabuf,
/*
* We use high-concurrency locking on hash indexes (see README for an overview
* of the locking rules). There are two cases in which we don't do locking.
* One is when the index is newly created in the current transaction. Since
* the creating transaction has not committed, no one else can see the index,
* and there's no reason to take locks. The second case is for temp
* relations, which no one else can see either. (We still take buffer-level
* locks, but not lmgr locks.)
* of the locking rules). However, we can skip taking lmgr locks when the
* index is local to the current backend (ie, either temp or new in the
* current transaction). No one else can see it, so there's no reason to
* take locks. We still take buffer-level locks, but not lmgr locks.
*/
#define USELOCKING(rel) (!((rel)->rd_isnew || (rel)->rd_istemp))
#define USELOCKING(rel) (!RELATION_IS_LOCAL(rel))
/*

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.51 2003/11/29 22:39:39 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.52 2004/08/28 20:31:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -232,7 +232,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
* page. We can skip locking for new or temp relations, however,
* since no one else could be accessing them.
*/
needLock = !(relation->rd_isnew || relation->rd_istemp);
needLock = !RELATION_IS_LOCAL(relation);
if (needLock)
LockPage(relation, 0, ExclusiveLock);

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.77 2004/07/21 22:31:20 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.78 2004/08/28 20:31:43 tgl Exp $
*
* NOTES
* Postgres btree pages look like ordinary relation pages. The opaque
@@ -483,7 +483,7 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
* new page. We can skip locking for new or temp relations,
* however, since no one else could be accessing them.
*/
needLock = !(rel->rd_isnew || rel->rd_istemp);
needLock = !RELATION_IS_LOCAL(rel);
if (needLock)
LockPage(rel, 0, ExclusiveLock);

View File

@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.179 2004/08/25 18:43:42 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.180 2004/08/28 20:31:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,6 +40,7 @@
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/portal.h"
#include "utils/relcache.h"
#include "utils/resowner.h"
#include "pgstat.h"
@@ -352,7 +353,7 @@ GetCurrentTransactionNestLevel(void)
bool
TransactionIdIsCurrentTransactionId(TransactionId xid)
{
TransactionState s = CurrentTransactionState;
TransactionState s;
if (AMI_OVERRIDE)
{
@@ -363,12 +364,16 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
/*
* We will return true for the Xid of the current subtransaction,
* any of its subcommitted children, any of its parents, or any of
* their previously subcommitted children.
* their previously subcommitted children. However, a transaction
* being aborted is no longer "current", even though it may still
* have an entry on the state stack.
*/
while (s != NULL)
for (s = CurrentTransactionState; s != NULL; s = s->parent)
{
ListCell *cell;
if (s->state == TRANS_ABORT)
continue;
if (TransactionIdEquals(xid, s->transactionIdData))
return true;
foreach(cell, s->childXids)
@@ -376,8 +381,6 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
if (TransactionIdEquals(xid, lfirst_xid(cell)))
return true;
}
s = s->parent;
}
return false;
@@ -2997,6 +3000,8 @@ CommitSubTransaction(void)
ResourceOwnerRelease(s->curTransactionOwner,
RESOURCE_RELEASE_BEFORE_LOCKS,
true, false);
AtEOSubXact_RelationCache(true, s->transactionIdData,
s->parent->transactionIdData);
AtEOSubXact_Inval(true);
ResourceOwnerRelease(s->curTransactionOwner,
RESOURCE_RELEASE_LOCKS,
@@ -3090,6 +3095,8 @@ AbortSubTransaction(void)
ResourceOwnerRelease(s->curTransactionOwner,
RESOURCE_RELEASE_BEFORE_LOCKS,
false, false);
AtEOSubXact_RelationCache(false, s->transactionIdData,
s->parent->transactionIdData);
AtEOSubXact_Inval(false);
ResourceOwnerRelease(s->curTransactionOwner,
RESOURCE_RELEASE_LOCKS,