微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL数据库Imgr——Relation Lock

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] 举报,一经查实,本站将立刻删除。

相关推荐