10-pg内核之锁管理器(五)行锁-结构体

时间:2024-09-29 18:04:14

LockTupleMode

行锁的模式,共4个

typedef enum LockTupleMode
{
	/* SELECT FOR KEY SHARE */
	LockTupleKeyShare,
	/* SELECT FOR SHARE */
	LockTupleShare,
	/* SELECT FOR NO KEY UPDATE, and UPDATEs that don't modify key columns */
	LockTupleNoKeyExclusive,
	/* SELECT FOR UPDATE, UPDATEs that modify key columns, and DELETE */
	LockTupleExclusive
} LockTupleMode;

tupleLockExtraInfo

由于行级锁是由常规锁和xmax相结合实现的,对于常规锁来讲,它就需要建立LockTupleMode和常规锁之间的映射关系,映射关系由结构体tupleLockExtraInfo描述。

  • hwlock: 行级锁对应的常规锁模式,因为行级锁模式只有4种,所以其对应的常规锁中的四种:AccessShareLock,RowShareLock,ExclusiveLock,AccessExclusiveLock
  • lockstaus: 显式加锁时的锁模式,有4种,分别为:MultiXactStatusForKeyShare,MultiXactStatusForShare,MultiXactStatusForNoKeyUpdate,MultiXactStatusForUpdate
  • updstatus: 通过DELETE/UPDATE加锁时的锁模式,主要有两种:MultiXactStatusNoKeyUpdate,MultiXactStatusUpdate

上述映射的行锁模式由枚举类型MultiXactStatus描述,类型内前4个对应的是lockstatus的值,后两个对应的是updstatus的值

typedef enum
{
	MultiXactStatusForKeyShare = 0x00,
	MultiXactStatusForShare = 0x01,
	MultiXactStatusForNoKeyUpdate = 0x02,
	MultiXactStatusForUpdate = 0x03,
	/* an update that doesn't touch "key" columns */
	MultiXactStatusNoKeyUpdate = 0x04,
	/* other updates, and delete */
	MultiXactStatusUpdate = 0x05
} MultiXactStatus;

tupleLockExtraInfo描述成员有4个,其结构及成员如下:

static const struct
{
	LOCKMODE	hwlock; //常规锁
	int			lockstatus; //通过显式加锁指定的锁模式
	int			updstatus; //通过DELETE/UPDATE加锁时的锁模式
}

tupleLockExtraInfo[MaxLockTupleMode + 1] =
{
	{	/* LockTupleKeyShare对应的锁 */
		AccessShareLock,
		MultiXactStatusForKeyShare,
		-1	/* KeyShare does not allow updating tuples */
	},
	{	/* LockTupleShare对应的锁 */
		RowShareLock,
		MultiXactStatusForShare,
		-1	/* Share does not allow updating tuples */
	},
	{	/* LockTupleNoKeyExclusive对应的锁 */
		ExclusiveLock,
		MultiXactStatusForNoKeyUpdate,
		MultiXactStatusNoKeyUpdate
	},
	{	/* LockTupleExclusive对应的锁 */
		AccessExclusiveLock,
		MultiXactStatusForUpdate,
		MultiXactStatusUpdate
	}
};

MultiXactID

tupleLockExtraInfo结构的行锁的锁模式都是由MultiXactStatus来表示,那我们首先要了解一下MultiXactID。
正常情况下,如果只有一个事务对某个元组加锁,这时是用不到上述的行锁的,只用将事务ID保存到xmax,并设置一下t_infomask的值即可。但是如果有多个事务同时对元组加锁,xmax就无法准确的记录加锁的事务了,此时可以将多个事务ID的映射关系保存都MultiXact日志中,并生成一个MultiXactID保存到xmax中,这个就能通过MultiXactID从MultiXact日志中找到对应的事务ID的信息。MultiXact日志的信息可以参考 MultiXact日志管理器
需要注意的是,使用MultiXactID时,元组的infomask要添加HEAP_XMAX_IS_MultiXact标记。
只有一个事务对元组加锁时,只需要xmax和t_infomask标记就足以表示。
t_infomask中行锁相关的标记位如下:

  • HEAP_XMAX_EXCL_LOCK:表示加的有排他锁,FOR UPDATE和FOR NO KEY UPDATE共用该标记位。
  • HEAP_XMAX_KEYSHR_LOCK:是一个KEY共享锁,FOR KEY SHARE子句对应该标记。
  • HEAP_XMAX_LOCK_ONLY:只有显式加锁时对应该标记
  • HEAP_XMAX_SHR_LOCK: 共享锁,FOR SHARE子句对于该标记
  • HEAP_XMAX_IS_MULTI:表示多个事务对元组加锁
  • HEAP_KEYS_UPDATED: 元组键值要被更新时添加此标记,DELETE/UPDATE操作加锁时对应该标记

每种行锁模式对应的标记位组合为:

  • FOR UPDATE:HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_LOCK_ONLY |HEAP_KEYS_UPDATED
  • FOR NO KEY UPDATE:HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_LOCK_ONLY
  • FOR SHARE:HEAP_XMAX_SHR_LOCK | HEAP_XMAX_LOCK_ONLY
  • FOR KEY SHARE:HEAP_XMAX_SHR_LOCK | HEAP_XMAX_LOCK_ONLY
  • UPDATE:HEAP_XMAX_EXCL_LOCK | HEAP_KEYS_UPDATED
  • DELETE:HEAP_XMAX_EXCL_LOCK | HEAP_KEYS_UPDATED