mirror of
https://github.com/postgres/postgres.git
synced 2025-08-31 17:02:12 +03:00
- Modifies LOCKTAG to include a 'classId'. Relation receive a classId of
RelOid_pg_class, and transaction locks XactLockTableId. RelId is renamed to objId. - LockObject() and UnlockObject() functions created, and their use sprinkled throughout the code to do descent locking for domains and types. They accept lock modes AccessShare and AccessExclusive, as we only really need a 'read' and 'write' lock at the moment. Most locking cases are held until the end of the transaction. This fixes the cases Tom mentioned earlier in regards to locking with Domains. If the patch is good, I'll work on cleaning up issues with other database objects that have this problem (most of them). Rod Taylor
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.17 2003/02/18 02:13:24 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.18 2003/02/19 04:02:53 momjian Exp $
|
||||
*
|
||||
* Interface:
|
||||
*
|
||||
@@ -855,22 +855,25 @@ DeadLockReport(void)
|
||||
else
|
||||
nextpid = deadlockDetails[0].pid;
|
||||
|
||||
if (info->locktag.relId == XactLockTableId && info->locktag.dbId == 0)
|
||||
if (info->locktag.objId == InvalidOid
|
||||
&& info->locktag.classId == XactLockTableId
|
||||
&& info->locktag.dbId == InvalidOid)
|
||||
{
|
||||
/* Lock is for transaction ID */
|
||||
elog(NOTICE, "Proc %d waits for %s on transaction %u; blocked by %d",
|
||||
info->pid,
|
||||
GetLockmodeName(info->lockmode),
|
||||
info->locktag.objId.xid,
|
||||
info->locktag.objsubId.xid,
|
||||
nextpid);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Lock is for a relation */
|
||||
elog(NOTICE, "Proc %d waits for %s on relation %u database %u; blocked by %d",
|
||||
elog(NOTICE, "Proc %d waits for %s on object %u class %u database %u; blocked by %d",
|
||||
info->pid,
|
||||
GetLockmodeName(info->lockmode),
|
||||
info->locktag.relId,
|
||||
info->locktag.objId,
|
||||
info->locktag.classId,
|
||||
info->locktag.dbId,
|
||||
nextpid);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.54 2002/08/01 05:18:33 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.55 2003/02/19 04:02:53 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -126,9 +126,10 @@ LockRelation(Relation relation, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.objId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.classId = RelOid_pg_class;
|
||||
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
|
||||
tag.objId.blkno = InvalidBlockNumber;
|
||||
tag.objsubId.blkno = InvalidBlockNumber;
|
||||
|
||||
if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
|
||||
lockmode, false))
|
||||
@@ -160,9 +161,10 @@ ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.objId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.classId = RelOid_pg_class;
|
||||
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
|
||||
tag.objId.blkno = InvalidBlockNumber;
|
||||
tag.objsubId.blkno = InvalidBlockNumber;
|
||||
|
||||
if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
|
||||
lockmode, true))
|
||||
@@ -190,9 +192,10 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.objId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.classId = RelOid_pg_class;
|
||||
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
|
||||
tag.objId.blkno = InvalidBlockNumber;
|
||||
tag.objsubId.blkno = InvalidBlockNumber;
|
||||
|
||||
LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
|
||||
}
|
||||
@@ -215,9 +218,10 @@ LockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = relid->relId;
|
||||
tag.objId = relid->relId;
|
||||
tag.classId = RelOid_pg_class;
|
||||
tag.dbId = relid->dbId;
|
||||
tag.objId.blkno = InvalidBlockNumber;
|
||||
tag.objsubId.blkno = InvalidBlockNumber;
|
||||
|
||||
if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
|
||||
lockmode, false))
|
||||
@@ -233,9 +237,10 @@ UnlockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = relid->relId;
|
||||
tag.objId = relid->relId;
|
||||
tag.classId = RelOid_pg_class;
|
||||
tag.dbId = relid->dbId;
|
||||
tag.objId.blkno = InvalidBlockNumber;
|
||||
tag.objsubId.blkno = InvalidBlockNumber;
|
||||
|
||||
LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
|
||||
}
|
||||
@@ -253,9 +258,10 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.objId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.classId = RelOid_pg_class;
|
||||
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
|
||||
tag.objId.blkno = blkno;
|
||||
tag.objsubId.blkno = blkno;
|
||||
|
||||
if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
|
||||
lockmode, false))
|
||||
@@ -271,9 +277,10 @@ UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.objId = relation->rd_lockInfo.lockRelId.relId;
|
||||
tag.classId = RelOid_pg_class;
|
||||
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
|
||||
tag.objId.blkno = blkno;
|
||||
tag.objsubId.blkno = blkno;
|
||||
|
||||
LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
|
||||
}
|
||||
@@ -294,9 +301,10 @@ XactLockTableInsert(TransactionId xid)
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = XactLockTableId;
|
||||
tag.objId = InvalidOid;
|
||||
tag.classId = XactLockTableId;
|
||||
tag.dbId = InvalidOid; /* xids are globally unique */
|
||||
tag.objId.xid = xid;
|
||||
tag.objsubId.xid = xid;
|
||||
|
||||
if (!LockAcquire(LockTableId, &tag, xid,
|
||||
ExclusiveLock, false))
|
||||
@@ -317,9 +325,10 @@ XactLockTableWait(TransactionId xid)
|
||||
Assert(!TransactionIdEquals(xid, myxid));
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.relId = XactLockTableId;
|
||||
tag.objId = InvalidOid;
|
||||
tag.classId = XactLockTableId;
|
||||
tag.dbId = InvalidOid;
|
||||
tag.objId.xid = xid;
|
||||
tag.objsubId.xid = xid;
|
||||
|
||||
if (!LockAcquire(LockTableId, &tag, myxid,
|
||||
ShareLock, false))
|
||||
@@ -334,3 +343,59 @@ XactLockTableWait(TransactionId xid)
|
||||
if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
|
||||
TransactionIdAbort(xid);
|
||||
}
|
||||
|
||||
/*
|
||||
* LockObject
|
||||
*
|
||||
* Lock an arbitrary database object. A standard relation lock would lock the
|
||||
* classId of RelOid_pg_class and objId of the relations OID within the pg_class
|
||||
* table. LockObject allows classId to be specified by the caller, thus allowing
|
||||
* locks on any row in any system table.
|
||||
*
|
||||
* If classId is NOT a system table (protected from removal), an additional lock
|
||||
* should be held on the relation to prevent it from being dropped.
|
||||
*/
|
||||
void
|
||||
LockObject(Oid objId, Oid classId, LOCKMODE lockmode)
|
||||
{
|
||||
LOCKTAG tag;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.objId = objId;
|
||||
tag.classId = classId;
|
||||
tag.dbId = MyDatabaseId;
|
||||
tag.objsubId.blkno = InvalidBlockNumber;
|
||||
|
||||
/* Only two reasonable lock types */
|
||||
Assert(lockmode == AccessShareLock || lockmode == AccessExclusiveLock);
|
||||
|
||||
if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
|
||||
lockmode, false))
|
||||
elog(ERROR, "LockObject: LockAcquire failed");
|
||||
}
|
||||
|
||||
/*
|
||||
* UnlockObject
|
||||
*/
|
||||
void
|
||||
UnlockObject(Oid objId, Oid classId, LOCKMODE lockmode)
|
||||
{
|
||||
LOCKTAG tag;
|
||||
|
||||
/* NoLock is a no-op */
|
||||
if (lockmode == NoLock)
|
||||
return;
|
||||
|
||||
MemSet(&tag, 0, sizeof(tag));
|
||||
tag.objId = objId;
|
||||
tag.classId = classId;
|
||||
tag.dbId = MyDatabaseId;
|
||||
tag.objsubId.blkno = InvalidBlockNumber;
|
||||
|
||||
/* Only two reasonable lock types */
|
||||
Assert(lockmode == AccessShareLock
|
||||
|| lockmode == AccessExclusiveLock);
|
||||
|
||||
LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.120 2003/02/18 02:13:24 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.121 2003/02/19 04:02:53 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Outside modules can create a lock table and acquire/release
|
||||
@@ -97,8 +97,8 @@ LOCK_DEBUG_ENABLED(const LOCK *lock)
|
||||
return
|
||||
(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
|
||||
|| (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
|
||||
&& (lock->tag.relId >= (Oid) Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
|
||||
&& (lock->tag.objId >= (Oid) Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (lock->tag.objId == Trace_lock_table));
|
||||
}
|
||||
|
||||
|
||||
@@ -107,12 +107,12 @@ LOCK_PRINT(const char *where, const LOCK *lock, LOCKMODE type)
|
||||
{
|
||||
if (LOCK_DEBUG_ENABLED(lock))
|
||||
elog(LOG,
|
||||
"%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) grantMask(%x) "
|
||||
"%s: lock(%lx) tbl(%d) obj(%u) class(%u) db(%u) objsub(%u) grantMask(%x) "
|
||||
"req(%d,%d,%d,%d,%d,%d,%d)=%d "
|
||||
"grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
|
||||
where, MAKE_OFFSET(lock),
|
||||
lock->tag.lockmethod, lock->tag.relId, lock->tag.dbId,
|
||||
lock->tag.objId.blkno, lock->grantMask,
|
||||
lock->tag.lockmethod, lock->tag.objId, lock->tag.classId, lock->tag.dbId,
|
||||
lock->tag.objsubId.blkno, lock->grantMask,
|
||||
lock->requested[1], lock->requested[2], lock->requested[3],
|
||||
lock->requested[4], lock->requested[5], lock->requested[6],
|
||||
lock->requested[7], lock->nRequested,
|
||||
@@ -129,16 +129,16 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
|
||||
if (
|
||||
(((PROCLOCK_LOCKMETHOD(*proclockP) == DEFAULT_LOCKMETHOD && Trace_locks)
|
||||
|| (PROCLOCK_LOCKMETHOD(*proclockP) == USER_LOCKMETHOD && Trace_userlocks))
|
||||
&& (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId >= (Oid) Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId == Trace_lock_table))
|
||||
&& (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId >= (Oid) Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId == Trace_lock_table))
|
||||
)
|
||||
elog(LOG,
|
||||
"%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%d,%d,%d,%d,%d,%d,%d)=%d",
|
||||
where, MAKE_OFFSET(proclockP), proclockP->tag.lock,
|
||||
PROCLOCK_LOCKMETHOD(*(proclockP)),
|
||||
proclockP->tag.proc, proclockP->tag.xid,
|
||||
proclockP->holding[1], proclockP->holding[2], proclockP->holding[3],
|
||||
proclockP->holding[4], proclockP->holding[5], proclockP->holding[6],
|
||||
proclockP->holding[1], proclockP->holding[2], proclockP->holding[3],
|
||||
proclockP->holding[4], proclockP->holding[5], proclockP->holding[6],
|
||||
proclockP->holding[7], proclockP->nHolding);
|
||||
}
|
||||
|
||||
@@ -417,8 +417,9 @@ LockMethodTableRename(LOCKMETHOD lockmethod)
|
||||
*
|
||||
* lockmethod 1 2
|
||||
* tag.dbId database oid database oid
|
||||
* tag.relId rel oid or 0 0
|
||||
* tag.objId block id lock id2
|
||||
* tag.classId class oid 0
|
||||
* tag.objId rel oid or 0 0
|
||||
* tag.objsubId block id lock id2
|
||||
* or xact id
|
||||
* tag.offnum 0 lock id1
|
||||
* proclock.xid xid or 0 0
|
||||
@@ -449,7 +450,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(LOG, "LockAcquire: user lock [%u] %s",
|
||||
locktag->objId.blkno, lock_mode_names[lockmode]);
|
||||
locktag->objsubId.blkno, lock_mode_names[lockmode]);
|
||||
#endif
|
||||
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
@@ -572,7 +573,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
|
||||
elog(LOG, "Deadlock risk: raising lock level"
|
||||
" from %s to %s on object %u/%u/%u",
|
||||
lock_mode_names[i], lock_mode_names[lockmode],
|
||||
lock->tag.relId, lock->tag.dbId, lock->tag.objId.blkno);
|
||||
lock->tag.objId, lock->tag.dbId, lock->tag.objsubId.blkno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -993,7 +994,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objId.blkno, lockmode);
|
||||
elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objsubId.blkno, lockmode);
|
||||
#endif
|
||||
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
|
Reference in New Issue
Block a user