RelationInitLockInfo
锁信息LockInfoData结构体,主要用于存放relation识别符和数据库识别符。
typedef struct LockInfoData
{
LockRelId lockRelId;
} LockInfoData;
typedef struct LockRelId {
Oid relId; /* a relation identifier */
Oid dbId; /* a database identifier */
} LockRelId;
RelationInitLockInfo函数为relation描述符初始化锁信息LockInfoData,其中relation->rd_rel是FormData_pg_class结构体,其成员也就是pg_class关于该relatioin的条目。relisshared描述的是该relation是否是跨数据库共享的。下面的逻辑就是对rd_lockInfo.lockRelId.dbId进行初始化,如果是跨数据库共享,就将InvaliOid放到该变量中。
/* RelationInitLockInfo
* Initializes the lock @R_92_4045@ion in a relation descriptor.
* relcache.c must call this during creation of any reldesc. */
void RelationInitLockInfo(Relation relation) {
Assert(RelationIsValid(relation));
Assert(OidisValid(RelationGetRelid(relation)));
relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
if (relation->rd_rel->relisshared) relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
else relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
}
SetLocktagrelationOid
SetLocktagrelationOid函数创建LOCKTAG结构体,我们知道主锁表用来保存当前数据库中所有事务的锁对象(也就是Lock结构体),其存储在共享内存中。对应该哈希表来说,其键是LOCKTAG,值是LOCK结构体,这里就是初始化LOCKTAG结构体。初始化宏如SET_LOCKTAG_RELATION所示。
/* SetLocktagrelationOid Set up a locktag for a relation, given only relation OID */
static inline void SetLocktagrelationOid(LOCKTAG *tag, Oid relid) {
Oid dbid;
if (IsSharedRelation(relid)) dbid = InvalidOid;
else dbid = MyDatabaseId;
SET_LOCKTAG_RELATION(*tag, dbid, relid);
}
/* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */
#define SET_LOCKTAG_RELATION(locktag,dboid,reloid) \
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_RELATION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
LockRelationOid
LockRelationOid函数通过OID锁定relation。该函数在尝试打开relcache entry前调用。调用LockAcquireExtended函数获取表锁。
/* LockRelationOid
* Lock a relation given only its OID. This should generally be used before attempting to open the relation's relcache entry. */
void LockRelationOid(Oid relid, LOCKMODE lockmode) {
LOCKTAG tag;
LOCALLOCK *locallock;
LockAcquireResult res;
SetLocktagrelationOid(&tag, relid);
res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock);
/* Now that we have the lock, check for invalidation messages, so that we
* will update or flush any stale relcache entry before we try to use it.
* RangeVarGetRelid() specifically relies on us for this. We can skip
* this in the not-uncommon case that we already had the same type of lock
* being requested, since then no one else Could have modified the
* relcache entry in an undesirable way. (In the case where our own xact
* modifies the rel, the relcache update happens via
* CommandCounterIncrement, not here.)
* However, in corner cases where code acts on tables (usually catalogs)
* recursively, we might get here while still processing invalidation
* messages in some outer execution of this function or a sibling. The
* "cleared" status of the lock tells us whether we really are done
* absorbing relevant inval messages. */
if (res != LOCKACQUIRE_ALREADY_CLEAR) {
AcceptInvalidationMessages();
MarkLockClear(locallock);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。