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