Lock

全局hash

LockMethodLockHash:存储LOCK
LockMethodProcLockHash:存储PROCLOCK
LockMethodLocalHash:存储LOCALLOCK

同一个LOCK资源对象可以被多个不同的 PROCLOCK 持有,而这些 PROCLOCK 又分别属于不同的进程。

LOCKTAG

1
2
3
4
5
6
7
8
9
typedef struct LOCKTAG
{
uint32 locktag_field1; /* a 32-bit ID field */
uint32 locktag_field2; /* a 32-bit ID field */
uint32 locktag_field3; /* a 32-bit ID field */
uint16 locktag_field4; /* a 16-bit ID field */
uint8 locktag_type; /* see enum LockTagType */
uint8 locktag_lockmethodid; /* lockmethod indicator */
} LOCKTAG;
  • locktag_type
    标识这个锁是针对哪类资源的。每种 LockTagType 决定了 LOCKTAG 里后面几个字段(locktag_field1 ~ locktag_field4)是怎么解释的,比如:
    LOCKTAG_TRANSACTION:xid
    LOCKTAG_RELATION:dbOid + relOid
    LOCKTAG_TUPLE:dbOid + relOid + blockNum + offNum
  • locktag_lockmethodid
    • DEFAULT_LOCKMETHOD(id = DEFAULT_LOCKMETHOD)
      绝大多数用户可见的锁(relation, tuple, transactionid 等)都走它。
    • USER_LOCKMETHOD(id = USER_LOCKMETHOD)
      提供给 pg_advisory_lock() 一类的 advisory lock,用于用户自定义锁。

LOCK

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct LOCK
{
LOCKTAG tag;
LOCKMASK grantMask;
LOCKMASK waitMask;
dlist_head procLocks;
dclist_head waitProcs;
int requested[MAX_LOCKMODES];
int nRequested;
int granted[MAX_LOCKMODES];
int nGranted;
} LOCK;
  • waitProcs
    等待本LOCK的PGPROC链表
  • procLocks
    等待本LOCK的PROCLOCK链表
  • waitMask
    该资源上等待的锁类型:目前有进程在等待的锁类型集合
  • procLocks
    • 一个 LOCK(资源)可以挂很多 PROCLOCK(不同后台进程),每个 PROCLOCK 只对应一个 PGPROC + 一个 LOCK。
    • 同一进程与同一资源只会有一个 PROCLOCK;它的 holdMask 可以同时包含多个锁模式位,且内部还有引用计数在 LOCALLOCK 里,不会创建多个 PROCLOCK
    • 资源侧用 LOCK.procLocks 链表串起所有持有/等待它的 PROCLOCK;进程侧在 PGPROC.myProcLocks(见 proc.h)里串起它关联的所有 PROCLOCK

      因此:一个资源可以被多个进程持锁;一个进程可以同时持有多个资源的锁;对同一资源如需多模式/多次持有,累加在同一个 PROCLOCK 的掩码/计数里。

  • grantMask
    该资源上已经授予的锁类型,LOCKMASK 每一位对应 “编号为 N 的锁模式是否已持有/等待”,位号就是 lockmode, bit0 保留不适用
  • requested[i]
    当前有多少个后台对模式 i 提出请求(已授予 + 正在等待)
  • nRequested:是总和

    “等待者数” = requested[i] - granted[i](或总等待 = nRequested - nGranted),依此可以知道有没有人还在等
    授予/释放锁时同步更新这些计数,并据此调整 grantMask/waitMask,决定是否要唤醒等待队列;

  • granted[i]
    当前有多少个后台成功得到了模式 i 的锁
  • nGranted:
    总和

LOCKMODE

每种资源支持8种锁(lockmode)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define NoLock					0
#define AccessShareLock 1 /* SELECT */
#define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */
#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
#define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL), ANALYZE, CREATE
* INDEX CONCURRENTLY */
#define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */
#define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW
* SHARE */
#define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR UPDATE */
#define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM FULL,
* and unqualified LOCK TABLE */

#define MaxLockMode 8 /* highest standard lock mode */

冲突矩阵

Requested Lock Mode ACCESS SHARE ROW SHARE ROW EXCL. SHARE UPDATE EXCL. SHARE SHARE ROW EXCL. EXCL. ACCESS EXCL.
ACCESS SHARE X
ROW SHARE X X
ROW EXCL. X X X X
SHARE UPDATE EXCL. X X X X X
SHARE X X X X X
SHARE ROW EXCL. X X X X X X
EXCL. X X X X X X X
ACCESS EXCL. X X X X X X X X

参考链接

postgres官方文档